RProtoBuf/0000755000176200001440000000000013164765764012157 5ustar liggesusersRProtoBuf/TODO0000644000176200001440000000673513005133352012632 0ustar liggesusersCurrent TODO list: o Finish improved vignette / R Journal writeup. o Push some type coercion hacks done in RProtoBuf upstream to Rcpp (Rcpp:as types should work on character strings representing numbers, especially for int64s since we don't otherwise have a way to represent 64-bit integers in base R). o Add more packages that depend on or enhance RProtoBuf. o Improve exception handling to prevent cases where an Rcpp exception crashes the interactive R instance. o Investigate Rcpp Modules support for some classes. Murray is not personally super enthusiastic about this one, as I think it may require non trivial changes to Rcpp and/or result in losing some of the user-friendliness we've crafted in the explicit RcppExported function entry points. Still, it could be explored and may result in significantly fewer lines of code if successful. o Add a FAQ and other documentation / examples. o Add more unit tests. o Explore removing the CLONE() in extractors.cpp. This makes for unusual semantics for any mutable methods of sub-messages. For example, clear(), setExtension(), and probably also update() ( but "$<-" on sub-messages is not a problem, it seems). More details below. o What should we do when we unload the package? Any additional resources to free that is not currently done? o finalizers [murray: what is needed here?] o Clean up formatting / whitespace of R code. The C++ code is now kept consistent through clang-format and a new emacs directory level config in pkg/src, and the style guide notes in the STYLE file on R-Forge. o Thoroughly audit extensions support and other deeply nested types support to ensure everything is implemented as expected. Stuff I think belongs in additional packages that depend on RProtoBuf, rather than inside RProtoBuf directly: o http-powered rpc implementation o More as.Message methods --- Detailed Notes ---- 8. CLONE() --[ examples from Murray illustrating the problem ]-- library(RProtoBuf) InitGoogle() if (!exists("protobuf_unittest.TestAllTypes", "RProtoBuf:DescriptorPool")) { unittest.proto.file <- system.file("unitTests", "data", "unittest.proto",package="RProtoBuf") readProtoFiles(file=unittest.proto.file) } test <- new(protobuf_unittest.TestAllTypes) test$optional_foreign_message <- new(protobuf_unittest.ForeignMessage, c=3) # Example 1: test$optional_foreign_message$c test$optional_foreign_message$clear() test$optional_foreign_message$c # didn't clear test$optional_foreign_message$c # Example 2: foo <- new(protobuf_unittest.ForeignMessage, c=3) foo$c foo$clear() foo$c # did clear foo$c # Example 3: baz <- test$optional_foreign_message baz$c baz$c <- 4 test$optional_foreign_message$c # still 3, but would be 4 if we removed the CLONE(). Example 1 is currently I think very confusing semantically for users of RProtoBuf with nested messages and I would like to fix that case. Example 2 works correctly now and would not be affected by this change. Example 3 would change behavior and could cause problems for users. Would need to be clearly announced in the NEWS file and to our user list. --[ Romain's thoughts ]-- `$<-` is the task of setMessageField: https://github.com/RProtoBuf/RProtoBuf/blob/master/R/00classes.R#L197 https://github.com/RProtoBuf/RProtoBuf/blob/master/src/mutators.cpp#L377 For "$" we could perhaps move to some sort of copy on change semantics (similar to what R does), instead of what we use currently which is more like copy on access. RProtoBuf/inst/0000755000176200001440000000000013164671424013121 5ustar liggesusersRProtoBuf/inst/examples/0000755000176200001440000000000013005133352014722 5ustar liggesusersRProtoBuf/inst/examples/addressbook.pb0000644000176200001440000000017513005133352017550 0ustar liggesusers < Romain Francoisromain@r-enthusiasts.com" +33(0)... = Dirk Eddelbuetteledd@debian.org" +01..." +01...RProtoBuf/inst/CITATION0000644000176200001440000000513513005133352014245 0ustar liggesusers## JSS publication bibentry(bibtype = "Article", title = "{RProtoBuf}: Efficient Cross-Language Data Serialization in {R}", author = c(person(given = "Dirk", family = "Eddelbuettel", email = "edd@debian.org"), person(given = "Murray", family = "Stokely", email = "murray@stokely.org"), person(given = "Jeroen", family = "Ooms", email = "jeroen.ooms@stat.ucla.edu")), journal = "Journal of Statistical Software", year = "2016", volume = "71", number = "2", pages = "1--24", doi = "10.18637/jss.v071.i02", header = "To cite RProtoBuf in publications use:", textVersion = paste("Dirk Eddelbuettel, Murray Stokely, Jeroen Ooms (2016).", "RProtoBuf: Efficient Cross-Language Data Serialization in R.", "Journal of Statistical Software, 71(2), 1-24.", "doi:10.18637/jss.v071.i02") ) # Also include the normal auto-generated RProtoBuf citation() # citation(auto=meta) RProtoBuf/inst/python/0000755000176200001440000000000013005133352014425 5ustar liggesusersRProtoBuf/inst/python/writemsg.R0000644000176200001440000000071313005133352016412 0ustar liggesusers#simple R script to serialize some R objects library(RProtoBuf) #some vectors serialize_pb(c(1,2,pi, NA,NaN,Inf,-Inf), "double.msg") serialize_pb(c(1L, 2L, NA), "integer.msg") serialize_pb(c(TRUE, FALSE, NA), "logical.msg") serialize_pb(c("foo", "bar", NA), "character.msg") serialize_pb(charToRaw("This is a test"), "raw.msg") #lists serialize_pb(list(foo=c(1,2,pi), bar=TRUE, baz="blabla", zoo=NULL), "list.msg") serialize_pb(iris[1:3,], "dataframe.msg") RProtoBuf/inst/python/runtest.sh0000755000176200001440000000040113005133352016463 0ustar liggesusers#!/bin/sh #write some PB data with R Rscript writemsg.R #compile proto file cp -f ../proto/rexp.proto . protoc rexp.proto --python_out=. rm rexp.proto #read with python and print python readmsg.py #cleanup tmp files rm rexp_pb2.py rexp_pb2.pyc rm *.msg RProtoBuf/inst/python/readmsg.py0000644000176200001440000000051213005133352016417 0ustar liggesusers#!/usr/bin/env python # # Simple test script to read a serialized message in python # import rexp_pb2; import glob; messages = glob.glob("*.msg"); for myfile in messages: print("Reading message " + myfile + " ...") f = open(myfile, 'rb') msg = rexp_pb2.REXP(); msg.ParseFromString(f.read()) f.close(); print(msg) del msg RProtoBuf/inst/NEWS.Rd0000644000176200001440000003660013164670750014172 0ustar liggesusers\name{NEWS} \title{News for Package \pkg{RProtoBuf}} \newcommand{\ghpr}{\href{https://github.com/eddelbuettel/rprotobuf/pull/#1}{##1}} \newcommand{\ghit}{\href{https://github.com/eddelbuettel/rprotobuf/issues/#1}{##1}} \section{Changes in RProtoBuf version 0.4.11 (2017-10-03)}{ \itemize{ \item The \code{RProtoBuf-info} vignette was converted to Rmarkdown using the templates and style file from the pinp package. \item A few minor internal upgrades } } \section{Changes in RProtoBuf version 0.4.10 (2017-08-13)}{ \itemize{ \item More careful operation in deserializer checking for a valid class attribute (Jeffey Shen in \ghpr{29} fixing \ghit{28}) \item At the request of CRAN, correct one \code{.Call()} argument to \code{PACKAGE=}; update routine registration accordingly } } \section{Changes in RProtoBuf version 0.4.9 (2017-03-06)}{ \itemize{ \item A new file \code{init.c} was added with calls to \code{R_registerRoutines()} and \code{R_useDynamicSymbols()} \item Symbol registration is enabled in \code{useDynLib} \item Several missing \code{PACKAGE=} arguments were added to the corresponding \code{.Call} invocations \item Two (internal) C++ functions were renamed with suffix \code{_cpp} to disambiguate them from R functions with the same name \item All of above were part of \ghpr{26} \item Some editing corrections were made to the introductory vignette (David Kretch in \ghpr{25}) \item The `configure.ac` file was updated, and renamed from the older converntion `configure.in`, along with `src/Makevars`. (PR \ghpr{24} fixing \ghit{23}) } } \section{Changes in RProtoBuf version 0.4.8 (2017-01-17)}{ \itemize{ \item Windows builds now use the proto3 library as well (PR \ghpr{21} fixing \ghit{20}) } } \section{Changes in RProtoBuf version 0.4.7 (2016-10-27)}{ \itemize{ \item At the request of CRAN, two documentation instances referring to the Omegehat repository were updated to \url{http://omegahat.net} } } \section{Changes in RProtoBuf version 0.4.6 (2016-09-08)}{ \itemize{ \item Support for serializing zero-length objects was added (PR \ghpr{18} addressing \ghit{13}) \item S4 objects are natively encoded (also PR \ghpr{18}) \item The vignette based on the JSS paper no longer uses a macro available only with the R-devel version of jss.cls, and hence builds on all R versions } } \section{Changes in RProtoBuf version 0.4.5 (2016-08-29)}{ \itemize{ \item Support for version 3 of the Protcol Buffers API \item Added 'syntax = "proto2";' to all proto files (PR \ghpr{17}) \item Updated Travis CI script to test against both versions 2 and 3 using custom-built .deb packages of version 3 (PR \ghpr{16}) \item Improved build system with support for custom CXXFLAGS (Craig Radcliffe in PR \ghpr{15}) } } \section{Changes in RProtoBuf version 0.4.4 (2016-07-10)}{ \itemize{ \item New vignette based on JSS publication (v71 i02) \item Some documentation enhancements were made, as well as other minor cleanups to file modes and operations \item Unit-test vignette no longer writes to \code{/tmp} per CRAN request \item The new Windows toolchain (based on g++ 4.9.*) is supported } } \section{Changes in RProtoBuf version 0.4.3 (2015-08-25)}{ \itemize{ \item Declare additional imports from \pkg{methods} in \code{NAMESPACE}. \item Travis CI tests now run faster as all CRAN dependencies are installed as binaries. \item The \code{tools/winlibs.R} script now tests for R (< 3.3.0) before calling the (soon-to-be phased out) \code{setInternet2()} function. \item Several small edits were made to \code{DESCRIPTION} to clarify library dependencies, provide additonal references and conform to now-current R packaging standards. } } \section{Changes in RProtoBuf version 0.4.2 (2014-12-10)}{ \itemize{ \item Address changes suggested by anonymous reviewers for our Journal of Statistical Software submission. \item Make \code{Descriptor} and \code{EnumDescriptor} objects subsettable with "\code{[[}". \item Add \code{length()} method for \code{Descriptor} objects. \item Add \code{names()} method for \code{Message}, \code{Descriptor}, and \code{EnumDescriptor} objects. \item Clarify order of returned list for descriptor objects in \code{as.list} documentation. \item Correct the definition of \code{as.list} for \code{EnumDescriptors} to return a proper list instead of a named vector. \item Update the default print methods to use \code{cat()} with \code{fill=TRUE} instead of \code{show()} to eliminate the confusing \code{[1]} since the classes in \pkg{RProtoBuf} are not vectorized. \item Add support for serializing function, language, and environment objects by falling back to R's native serialization with \code{serialize_pb} and \code{unserialize_pb} to make it easy to serialize into a Protocol Buffer all of the more than 100 datasets which come with R. \item Use \code{normalizePath} instead of creating a temporary file with \code{file.create} when getting absolute path names. \item Add unit tests for all of the above. } } \section{Changes in RProtoBuf version 0.4.1 (2014-03-25)}{ \itemize{ \item Document and add a test for the deprecated group functionality. \item Add a \code{CITATION} file pointing to the arXiv.org preprint. \item Fix a bug in the \code{show} method for \code{EnumDescriptor} types. \item Import all top-level enums from imported \code{.proto} files. \item Removed duplicate enum value type from the unit tests that caused problems with the most recent libprotobuf-2.5. (without option allow_alias). } } \section{Changes in RProtoBuf version 0.4.0 (2014-01-14)}{ \itemize{ \item Changes to support CRAN builds for MS Windows. \item Added functions \code{serialize_pb}, \code{unserialize_pb}, and \code{can_serialize_pb} plus documentation from Jeroen Ooms RProtoBufUtils package. \item New dir \code{inst/python} with some Python examples. \item Added Jeroen Ooms as author. \item Vignettes have been converted to the R 3.0.0 or later use of external vignette builders, no longer need a \code{Makefile} \item Added missing methods to dollar completion list for Message, Descriptor, EnumValueDescriptor, and FileDescriptor classes. \item Add missing export for \code{.DollarNames} EnumValueDescriptor to allow completion on that class. \item Add more than 15 additional pages to the main Intro vignette documenting better all of the S4 classes implemented by RProtoBuf, updating the type mapping tables to take into account 64-bit support, and documenting advanced features such as Extensions. \item Added better error checking in EnumDescriptors to catch the case when wrong types are provided. \item Updated the FileDescriptor \code{name()} method to accept a boolean for full paths just like the generic \code{name()} method. \item Correct a bug that incorrectly dispatched \code{as.character()} when \code{as.list()} was called on Descriptor objects. \item Update FileDescriptor \code{$} dispatch to work properly for the names of fields defined in the FileDescriptor, instead of just returning \code{NULL} even for types returned by \code{$} completion. \item Added a reservation for extension fields in the example tutorial.Person schema. \item Support setting int32 fields with character representations and raise an R-level \code{stop()} error if the provided string can not be parsed as a 32-bit integer, rather than crashing the R instance. \item Update the project TODO file. \item Add better documentation and tests for all of the above. \item Corrected the handling of uint32 and fixed32 types in protocol buffers to ensure that they work with numbers as large as 2^32 - 1, which is larger than an integer can hold in R since R does not have an unsigned integer class. These values are stored as doubles internally now to avoid losing precision. \item Added unit tests to verify behavior of RProtoBuf with extreme values for uint32 types. \item Removed old exception handling code and instead rely on the more modern Rcpp::stop method maintained in Rcpp. \item Add better error messages when setting a repeated field of messages to inform the user which element index was of the wrong type and what the expected type was. \item Add an optional 'partial' argument to readASCII allowing uninitialized message fragments to be read in. \item (internal) Added const qualifiers in more places throughout the C++ code for type safety. \item (internal) Standardize coding conventions of the C++ files and run them through clang-format for consistency. A STYLE file has been submitted to R-Forge with details about the coding standards and how they are enforced with Emacs and clang-format. \item Applied changes suggested by Kevin Ushey to the \code{S4} class handling to support both the currently released \CRANpkg{Rcpp} as well as the currently pending next version. } } \section{Changes in RProtoBuf version 0.3.2 (2013-12-15)}{ \itemize{ \item Fixed a bug that erroneously prevented users from setting raw byte fields in protocol buffers under certain circumstances. \item Give a user friendly error message when seting an extension to a message of the wrong type instead of causing a C++ check failure that terminates the Rsession. \item Change object table lookup slightly to allow users to use the \code{<<-} operator in code using \pkg{RProtoBuf} without hitting a \code{stop()} error in the lookup routine. \item Add missing \code{enum_type} method and improve show method for EnumValueDescriptors. \item Improve documentation and tests for all of the above. \item Rewrote \code{tests/} script calling \CRANpkg{RUnit} tests } } \section{Changes in RProtoBuf version 0.3.1 (2013-09-13)}{ \itemize{ \item Added support for setting and getting 64-bit integer types as character strings of decimal integers to work around R's lack of native 64-bit integer types. \item Added better error handling, documentation, and tests to the extensions support (getExtension and setExtension). \item Add support to P for returning extension descriptors. \item Improved error messages to include field names when invalid fields are specified to protocol buffer messages with new, update, etc. \item Improved configure to detect and pass -std=c++0x if it is available to enable long long 64-bit integer support in Rcpp. \item Improved configure in the case when pkg-config is not available or does not know about the google protocol buffer includes. \item Replaced newly deprecated Rcpp macros with a simplified macro functionality to avoid warnings on the latest development version of Rcpp. } } \section{Changes in RProtoBuf version 0.3 (2013-07-13)}{ \itemize{ \item Added support for Protocol Buffer extensions through the new getExtension and setExtension methods for Message objects, and added top-level extensions to the descriptor pool. \item Added more user-friendly \code{show()} methods for Messages, Descriptors, and other RProtoBuf objects. A common source of confusion on the mailing lists is to confuse Messages and Descriptors. The new \code{show()} methods succinctly display more information about e.g. the number of set fields in a message to make it a little clearer to users what type of object they are working with. \item Added has method for EnumDescriptor objects to test existance of a named constant in an enumeration, and fix a bug in the length method for these objects. \item Added a number method for EnumValueDescriptor objects to return the number of a named enumeration constant directly. \item Improved documentation and unit tests. } } \section{Changes in RProtoBuf version 0.2.6 (2012-10-04)}{ \itemize{ \item Applied several more patches by Murray to \itemize{ \item correct '_' and '__' mismatches in wrapper calls \item update a few manual pages for style, and add examples \item fix a bug where NAs were silently treated as TRUE for logical/bool types \item fix a bug that caused crashes when adding vectors to optional fields \item fix bugs in readASCII that returned empty protocol buffers when the file or connection could not be opened \item distinguish between non-existant and not-set fieldswith has() by returning NULL in the former case. \item fix a bug that caused non-deterministic behavior when setting a repeated message field in a protobuf to a single Message. \item add unit tests for all of the above. } \item Added Murray to Authors: field in DESCRIPTION \item Removed old and unconvincing example on RProtoBuf for storage and serialization in an imagined HighFrequencyFinance context } } \section{Changes in RProtoBuf version 0.2.5 (2012-08-08)}{ \itemize{ \item Applied patches by Murray to \itemize{ \item correctly deal with nested Protocol Buffer definitions, and also add new unit test for this \item test a a protocol buffer for missing required fields before serializing it, also add a unit test \item add a small stylistic fix and examples to the 'add.Rd' manual page } \item Moved inst/doc/ to vignettes/ per newer CRAN Policy } } \section{Changes in RProtoBuf version 0.2.4 (2012-05-15)}{ \itemize{ \item Applied several patches kindly supplied by Murray Stokely to \itemize{ \item properly work with repeated strings \item correct C++ function naming in a few instances \item add an example of ascii export/import of messages } \item Suppport g++-4.7 and stricter #include file checking by adding unistd \item Made small improvements to the startup code } } \section{Changes in RProtoBuf version 0.2.3 (2011-04-12)}{ \itemize{ \item Protect UINT64 and INT64 with '#ifdef RCPP_HAS_LONG_LONG' which itself is valid with either g++ <= 4.4, or newer versions if the -std=c++0x is used \item The documentation Makefile now uses the $R_HOME environment variable \item The documentation Makefile no longer calls clean in the all target } } \section{Changes in RProtoBuf version 0.2.2 (2011-01-11)}{ \itemize{ \item Applied two patches by Murray Stokely which \itemize{ \item correct a typo preventing some functions from being called, \item add bounds checking in call to google protobuf library, \item add a new name method \item add a tiny unit test for the above \item add more graceful error handling \item add support for import patterns other than .proto$, \item add simple reading file that does not exist (exception) test \item add simple repeated field unit test } } } \section{Changes in RProtoBuf version 0.2.1 (2010-10-18)}{ \itemize{ \item Support for raw bytes added thanks to a patch by Koert Kuipers } } \section{Changes in RProtoBuf version 0.2.0 (2010-09-10)}{ \itemize{ \item Second release with numerous internal changes made possible by changes in Rcpp } } \section{Changes in RProtoBuf version 0.1-0 (2010-02-01)}{ \itemize{ \item Initial CRAN release } } RProtoBuf/inst/THANKS0000644000176200001440000000021213005133352014012 0ustar liggesusers In alphabetical order: Koert Kuipers for a patch adding raw byte support Murray Stokely for several patches and helpful discussions RProtoBuf/inst/doc/0000755000176200001440000000000013164671424013666 5ustar liggesusersRProtoBuf/inst/doc/RProtoBuf-unitTests.pdf0000644000176200001440000017755513164671424020267 0ustar liggesusers%PDF-1.5 % 5 0 obj << /Length 580 /Filter /FlateDecode >> stream xWMo0 W(/ҎE{vp& ~Hv] vY;Ж(G=R1nb.ޗbӥ4:w1sL`E Ul='xDfoE7pztkdFBN|/VOk`,7eK15%8Jx[c*l ǰů%r-nlMڢ>y[Z?%Q'$C2(a-ݴ|cM =-LC EDMax|湆aEs,\o("*S h6m`36_ oƎl-_6hLzHeAȨZzEh q#*ߏg%76& ѵ!wT*\M"ʕq-YoF*tqm.y`WJoΤwGav5i, U}<% Yܼ Q{&k 9On)o)a?޽λ 9"g.zEaízטoWjmR|W,_ endstream endobj 17 0 obj << /Length 656 /Filter /FlateDecode >> stream xYMs0WxXl80p|nIL '[KKۇ77+v ׳|4X^ys&Cc|~ sŒ', ďEEJe֢+XZcnjpE(A$< e0 .,Vv+Ddx@5aխ~ LwԃkBV 1_![CG]p2#!'1Vܬ1]Wc9ceVNn= ][pިfV]=sf@B P !Sϒ:~z *G `9>`ljqr,:KkfjN'nr,~q1<)dw.UP!r?EpMy,YMU,*f۹Àf7[6J~2M GiL JafBdV=Mg 6Ӯj(Q8Oc+be!|6d"RܫDzΆ̹O:tz'(""<~n`SA/\V鱆LYg<沨Wvd|أZm捬?L ەgQI&A{28Gz- endstream endobj 22 0 obj << /Length 843 /Filter /FlateDecode >> stream xXKS0+|!ikŲlHmpO@;)IG2qO$ P,VԮx'^}\ 0+ͮ2%aC/nDS;hme0 . SBA 8TfIY;ݮY[K۾ yoa;MgX8p4Dg̰:?-+P>cdS꩔~&KM@ރz6?^{vOi75Wn 7|3ܞ xhWee@aYl&'#$ŕBy;U\STkO6iNRʵ5؆RAjj_ ۄ-Bn5i=?_ڥ1Kv%i\-SM倖*!<&dD/i2I@)8j/Z#ܽ i,22Qt跤sf.5owݤ#{pC_d@dEzr ]Qufy k9qu.h;wLƙ1ntJf_DC "Yh[ aO:}kG&-8 q'ІPC*X.MQ{bԥ #J5 7܆| EV֧ *7Up ;[eACoek~oYT/)q`5O'Sl$*8֋.sSAU5гXFFUꃪ7f%~;5U)ꢫ}%iomWu endstream endobj 27 0 obj << /Length 777 /Filter /FlateDecode >> stream xZK0+|d1譫JU[[UQxTm}dN6>b'&&:6VSiN? >fŧk}!!f\ -5BC!Wbj^Pl'v3}-Z/q>Z=qVdsB,U;T71rW,6fS;Weყ@4v\ 5ivUhV 9E9}y;wn+h9]%u&t ϝgzO |Mwh'bM_\ )N*Eg6:Q[p;SwFe9!i<^1z9wu$Ԗ<'S endstream endobj 31 0 obj << /Length 194 /Filter /FlateDecode >> stream xő10w~ō0pОDLtpFFq{Kw},"%GY5)h5lg#1}́i^LEUV2Ag뫘r(I \ZӥZwCgnRl#|Tn4"HRI!M}jJ endstream endobj 33 0 obj << /Length 104 /Filter /FlateDecode >> stream x313T0P04W0#S#CB.)T&9ɓK?\K(̥PRTʥ`ȥm``P73`v(PՓ+ L5* endstream endobj 42 0 obj << /Length1 1538 /Length2 7971 /Length3 0 /Length 8990 /Filter /FlateDecode >> stream xڍ46E ;3Dhѣ1N A5ZN.>{{[y~>g쳆ACG i G"P< ^๪ x@~< یǢur!b ?bH_kӿNRCީ `M@YB;M{ y8D낺U khep)wc 0gy;J캿g C@5ΰߏ n vw ws[! H/(;9= @whu#a/ F:O!Qo$z7cBD `">wX@!P>@\?:kҿW uB&/?6WJӸ~{6ʲ5rI>T:xvYDjk;Sfyj#!-/t<:Rk7z~v h-,9."yn _OjzOn_Ke8%#dߝht${^9 g;RŸ\s+3% I0F2ŤWIQ³,θzT4(Ky2fAҝzA5+}5WKu|Soy&- vWs].> y!#ĉcF:mYY֗sW"7ShlO1Qb٤/-q~V6XW]dn{g៬d0V,(w/>>0}%,>9(z1gVWҩ+\-}w < kx箭%N/B}hU䊋>unzI(?k{;1lSbb6yaJ [-?O'Ujr!Fr]KͬV~~> @CKEgxt=2 *P\)˕q70R| ,UO&`хdßx14Ex GPjnQ4\;>a<;—BuGig9(3w=']!4]`Q< PO*3a>Jǎ=Ro;M#V9n}1;c3с qP U K\˦ְrMRI10[UOV5&BXT3#?ў6K̓܋9Kgߠ)|OvYHfw -7S!bjk.]!i'd ʥ.:{f|^kKI |d KU;+`vh2zUrl+3:5&B7dgAK.8aҨhW{P 3E9yχ %+ҰPOvrN&gՆ]7%#S8"FrW_%z}z-)7SA2_N2a䆎>>ՠ|t@GX&s`ǶAe={a[t#z`V›o$َg+FEv5͙\`ft[qd:^jU y?5U݂7׽{~?CdEaSiӔHـK!21zP#H|ʕ~bEIR]}u(/feKA.n#.Jf.E]΃3LM{Ϲ֘<_gѺ V䶖#kQ(~lK ~Il ^QPbZ}>r$p@,$U+QYջr8 95ƔqsƱh&0VW]o1H=W#)^ p35޺MN1Äv"9R&خ6=7>"TL+E`Z/iڗԪc&՗s.TmE2z}0(&L]Y{YMKg'RҌ!I7O,_`2~tYBq@<*ڈ3m@;VEO @yⵯhF뽸2Ϗ9'M|\C܆U-K GWhx^+$}H-S~Ƌ>™]([h|kGd xL՝_x݆ru{pJg)ÀlbOb8m݊ᨺFrb#O@Aq,LGu{F=15N`lèZRQF ZLÉXeԲ O57~9- C䣎p/KB1{w HmjvW *8vwk= kQG sVOtͳ+.>!sbQ>_0aMia6vV㮻bLT^j˴z PD;@Dyaq-OP,s PHsYϷ>uV(%{mXguՈ ɦA"7m2{1!ok'v_u>N)`/f%SG2p '0XU*΋CYS1 pXJ*lE κ@mLgBn[rr uᐳ]ŝJZX6Y|lLt+a]ȡoÛ^;Kt!muޑo)J%SO+ĹָSΚ XAO+M?v,3 D~+U(xJL閛z3Da"P)c?F;)8 N.! 7OŢtPN j֑ %~(!0-oyiL,™Gߟ!sucR@Id!_lG횊 ı|bzD.^֊ ѫ_?$He0dUGA_.iwD:9Uu٤SsF5yT(ҏ/xJLSAM9qڧY %`t)ꢍoDiFg:ů4[6ֺ|߻xKأUaQuvŇquX:T:B}%/щS({1j$l%X%8-M[6Ah&bZ\wHoK$b: -8'>)vAŶ΂8ѷLpr>p 94D"2-G2QDzGMwR]-N&)u}j0UӋ;{X﷦~" $`YiS*+~NYw4DQgOOAEߘw'%Jc$ĕݛ *X'}=s/J.Gu# l-Nw pv:unufzcx$x #/ZSJ>K:^?%G r]GQ &_ǯ&aמ9U2rXoaK67fC,/z bU[Ɉc&CL4#n_ %q0%W % Je#3e♱6>]~c:B#S:x3^ܫo3\գO)?VHf߰īWXumQ]ilU)GS|2l hsIrf.E.XvYH5v=v^=s~o[`07* /v&8aȭ_myldKHI/ |Y8H4G] /Q+YuP[b߯`+]K,t&/+oqV= T!It9]-{&x K6$dRD:'!W`ll!r-z\d9c!`yz'AnG >erq{] ĺYFh8:=-wg<%IRL1Rs&0/`IZ~M6b(Ӹp֕Ʃgj|}p^ķ0wr{*WQ< wxON C!p_+`x:fnh;vK14.Fo}~SJ:LK4ep=onAULӫ~^pVKrėJ\ p}[W ( 0ry$n]7UjG5z436xR[ϞW/4mQ;xe?#R}㼎>IQ6U]`?~QL''ZxsVZ270|Ng\8zC,0lE_N-,2?F7gYP xEvx%!m帽&ꍖ_DLox%Z{u}ewBUՄP 䦉 I i]d㽲':4>2R+[hcwfKLYoKY~@M=oq̝~|Kn9oyeMBIK=- AR^-.̓sx 5'̙O+VI/c'=,;I`o)e\.*܍=tld9=)ϻvFL:4VŐdw @ޒ0YE߬wI~k>\LSph%?Xrg$bG"^5j| n׵|uvHgMO/x1ߗfuG[(w5jԆjK ٙRDĬ=Qf^b)L.K2%{ﲋ&Y7܁8uռi?r RR׎ވv (8\2AY AG644G܁Bmзp Vẏ]rnb"m?@6Te0@ԣ +h)koL2%YЄIe]]*B4b(?@m)\^0"n5|PwQ_?F*CaۨxrƤI3㉇X+!"c,Kbw'Ȓz̀ b/<7xvӓs?x{)RH,'x[8\n6q~fPvKCpUʺ$6I#ܕ#7[/B}2OtfpP%eyPFrFru;_ž2 !;괒:4Γ9U|XLB" "|am6dm@b$9'!Eۂj? Tl59"NݽcܯM6]A0/v }-Nlۘ,ۇnj}*=F1Xݍ*sk~|ܩO~$#ؙ!OTn)7+q&cj(Eۆ.$Hq=AA+ L6}j`󓖓!¹`1p aͯX-}&lsMH*ǜמ<&|xv2{t;Ni(᫜>}1;-@cs qikOdubxAx#>Ukw5\pLY՚%9-5[2NoT >/u 67WDgTuRzH،iThf(# 唘K!&K#lp<oJdxTi}()l{r_fC]n@(ƔoV 3 zvl|4_4 {.bfVq?uBZ6Az:#cMmI!ҲqwRw$Ri5|="]w%-cMG^L¨p,"Wn6uhRv$_"LƊ{z&ȥ $;Ǝ {~S1&{iw:[^y-F6LiRk*Umo>g] i_'%cN#ttV:a%`yF#dSFvt& endstream endobj 44 0 obj << /Length1 1433 /Length2 7339 /Length3 0 /Length 8316 /Filter /FlateDecode >> stream xڍT]6,) RCw )Cw7 080t R- JҍJ Z߷f{ξk}9{-xM= ?__AX Hw(._$;&P8PT //")P{B5ǢpABPwk `D\ H .w;ځa}G vI'Uˋ΋@:Jsp('~7 @`u G8HA p= v"kE}6 /  C>P# A(o7 Mw`O0# w ݞru~;)+..8w}P$}٧po w݄+!QUrsbm;+  pku=!ߎZx@ jBpd!wz{ey'/{72T?!~0?[dwC.bU_ӿ*[w#r ~a~YB;M[f.P߄;z@q7CZM=( a>F; ׁR_)A;๻ݍӻN\Jp;H%Y?,C GBwH7*,sީ Bb? 億x!(?_N!$[Q{KEy\Q<{=haUXvo~dsn˥+QޑmZ\ k7MhX<䒜yu+{>ZݨQǿ*gkR4c9IɈ$>&8>'W{Ņ'Xg"|w񝁀{;3%-1VŴ_qBwd}CG[PxCWZk@8u/ZbUI5Q:U%BA~Ĩ9fNK-`⡩vpce^g)g V;dzdhJN )X!vc*#9O~?/=B"@4̋26LDcA>M3t9K/t%!ua|+伊%> ߄g~1*wOW D[8 2 mՅˇEto};)+"0:?(x@4<vwTe.\[]yORCW^ܥ,l=%#g-g ˒??nn>c y &북7 r|WuMZe<+(nHǦb^2L-KF8D7.zTOBw1 JK24 Ho:͔(UnQDz,Q&enƼ(ewtJuo]x_uZ4e*-=*iDV 8b"LBq춈bpJNWLG##^EFr3*GFXɋ5]6|O UzO;^ )hk}{rJe:(hы$~mBWrxs8&^2_⏓z+e|&ci`);|{0N]2T62GփX?=֑NIFT>Imj @{ ^*ÂתʫN|(nX,-7<ӭOUsT^n<_-;T;27Od2i rHc:H4bλNcB8JL^m<;A:۳.mq Uffw<+8TӬ,IjT@wݔK ّ"i-{:݊}.^SO"55F9>{,^f4:-Z?uPtۥN@]S8 1~v8Af;tp[Gw7s؋wdUMM6d(Qٽ1D^YR5ŧZG9ݹĸ8F[OފVO ]c=m)^-YT7O}EK9auP%s~JlCM޶"1MpڔI3r& J57w֔ |!UCxrL uļ#iB][ޗq6tGw#D  񤓶`u]_={\4>/N>c5ZRﲚ0%v~Odn/J5}$V2ލ>i(MCS^Mw})Y*s Cejɚs_15Ct\\Eь!]3KhJ!8À=ݛ]I c M_w03a^p*5Y G:%tbq4%cc"de kPTq}N$ ^H픞yR1`MdܜK{p[45䮪ݓWaMjMÄx=! XU ||ZWsc>JѼz!@p99}sa*rI2Q& zc뀫F8+i>1*8C/c$"^}Sk!\`c_J8Ϧ$"*OyM۲}OrL4`T gacZM×{ EL6ӣpS?yA'mM3*,:ha*x\ӎ_R.R}aW~ȌӶS ̆U׳O<|ɋG=ܺ;|-'3/w >96*#+!!iAFnFɥylt(G}6"]̂L=V+|X 5 JQVlȴ% BWUdCF®6n_{ v* |)EsO)Ԕ|TVNV7 ,$DN߬ ~;[z^,GY_*Jbsm8:91^YkX}iRV?.n\SE :ȅ.A=w.u|!6E>Nx|"2nΞ^" QE`4[34ۈD-&zU8Qz ؄yq ^;w [_X*{m#aRv'vWH G:ZLڮߙovd?f!}h6g1ГM-DmզZ͉P?6~dàۼNX;`:9C p8qy=AބXS/9 *a2f%G1?H7n>٥wcϻWt$-~p/ikeq3lZb-[KoqEcG?k/=jAc]$&>F/8[OndL,;ㅊU҆rӧӬ:F4 7GN FEw8zRUoћD)>ӓ@]k:w_/ |*j+!$c %lNQ~_G9E L*qhҲ~R{UxX8Y+gYijZ)sy [ᢽM{#l';]A {#e)nMrww7+V|%n]'hN=+dBҳ4gd9$l4[osnBVv&SMƊr[ot$[Oƙ_d7N/,6_ZM$b>HmP}1!rs=-SWV›x-O9ڷ{HN*oMح:,aˆ7sFAXH%UZ*CFe weg@ZM:$q8Oa 94^sXcE̴F~UaA|;'N[XϠvonL ۼZ{wąaa3I W%4z$oAp"}%>`d}> =Y(Ʃ@>^g7C/h8sc 18q\C)> aaAƅGŁ#Ig2 {g(n}>=.b1B arRd)Jѧ .kr4?XTۿeAHG9m#7ufzy0ˏH1mh+~ڥªO7wǙ7t{,ycun #O\S"[픻>ڻ 9ͰeO~]%&2C@5בJ$ς HN4AfGlu>(w99Vhjн]i\E'"偬iFPҘ;pd5A'.S7YКdOY,r̺ [kZ>FʎzZ ù_ 0 .\\GH&j*qv 1Np'-,{|zwV!(z@%jݑ:)ciصsF{]*T %ͽݖ z}1#ئh"yfnSy 0S_ܩ`]."+V|{c;kY@yf-OyZ [Yxfd7sA?'#M{Zʑ@#)u{0үswymINSJ-g`SOOR(v"G7[$‰^S&v+@\G G{Kpd#j -1P 2+[[̤!L{MjvDun9 | |FPX]3&G Ȋخ0*6j /&N֟ǘxy?mJ,톳(m?jۛ)}m|hG BXYD32f3LIv+2 4rDq2QX yXJdwȉWJxꨆD?o}fU+6ƑeU-C9I4Ƽn va/e 9|ڝMt]%5!mɽäܜxm"&b ^ts*ѢҀBc#3DGa8O?ӕKIε+wU4˯(껛yvnnW2~*Q_/]k9E^mD {U̶\U7MɁmj."ٓB̽]9hMvi7:pP;&6<u}) ҖJծ_w={'.ؚ> r V){jmeotQcf%3'k&7=AsUy&Ѣg)[4.8%pUP`r&(yu"<årl~_8wد+dhI72șD@5 endstream endobj 46 0 obj << /Length1 1900 /Length2 11857 /Length3 0 /Length 13040 /Filter /FlateDecode >> stream xڍTj6 (t5tww C3%)%t7HwI HwJ sYkk}_RME,cqfag $59@ '+ȁBCel njB:YCEA6)3OPpsyy@?D{@ jePf(CN(4P+ K2@o`e+ nZ e%)iojvBllnnn ;'V{3vC]fT@v'cEhYZ9m״7wvAg)1CJU0of?g`geO' 25sA< s+[0@UFݙ&lA +[3Aquys2Z98;:YwSIف!N(M݃ػAV3C8iC]RPM(l`g7`wSK<9'rw?2?x9\g ߎF(3+Sg 'l7~|;=v? efC~䵕h0=|/N. 7; w5?]C7|JӰ?On0;h? >aV_!ݐ_n7³f]lM`3+w=8?h$c6Sr6[,۵/fdUY6/ӳ"rKJCL~o7o lV#{6l۳|d |lg?o^ٟW/Ͻ87]9s=gK(OgŰ9+yq\@|vzGL]''Yz`w)œ`uMPm84Ͷn212=`z-0ԍ)M%Hu\]v+WC>2dR-GGoͰ 4َ.|j8n}%Gw*yQJX"#dR!8!1bc\]OcgMnvs[EnDK3!@ODWcj\]eWª9ojՓ-o-*v}V"=^c%^B-; 6=4ob!`2n}?4Ys߆EzВ̙T&-i}ΘlM}}^UKB*G 2kfxHfz5ԁw5ۇ i{}n(}%%O|XrQwp!c._VCB~^w_}81c XhJ`~TQ:Ή&1%PC% ɫ' W2'ͼJӱ @h~XNgwCXڐ ڕs\8|%]rvM*XΕЅв,hV}0 /O`PIIe,"O_0qjN`Q 3GD񪃆æ{k^CD&f:lo&]G~tO ͏ʗ ߅#~>M[Q SvZop<7Y|sUZ);f4-%F&bG32҉*egբ:SSiz$VÊh])IKݢɴi\p3 I{pyyrA|tRpTz; eCDܩWqE šIc+~Tn}/ h]y;K'o|4v',W~w޷վ,1 e4XϕoEÂؤ/^l*dFԊg1d'"#ᦒi?{Dr_9|:mҾi:ǡ%}Itwg{NdAPOTPKX{HҶ0RylGu;+^xx_Hى:&F6iL_t~bx)KY7Cd:V>Tl;3eo̱Z5+BU2uöM͛Ag [i60me R!)9YhM\ GF@n$Oo]pDR4 1?A`2Gc-7졈)Y U >U`8sʒΡlj=uL'F('@RQCt}tV #m3י+IcQKܶv=7fR1ƥ8e m0t@M81}}gohD'l֑.ވ)C]uiD1.d9-~  4-#7su╊~<XH]Lkնx.r.0j5W|6֘g1袗.?Wt3,卢*vS3ZrN-;t<]D#$qbpl#Y\e˲fȘzmam %t&(p^8[%Itv8A?jaUF".*ܛUQgRH߬~}3Ff8ҺUk+*p+o{&˳/C>stʈO3=[Ҩ㋛4yԏF+H..6 #:߻9۱KU-'RRkD]c<I휛+TO>)M4ܳ{(?Q >847W\^$("_2ΐ ւvh\Thm3ɨ*Z[hֵ kɴC2LQ&(ٶE:TrM%[f7iQ5~|eoBRQЈ+q>M CDAXo+Fq-}Q|STo6'bd(($P SNg56=sD8ηc۳G (XVCOA<, AD"}@Zn-A &xՅG#a~YnLJ@mǺq- [uWDũO3f}.u>.s )4{.1;8*D/w$_KU_E0?𱮑(=]b/yUע3J|pЧ䰎J!x?*C܎i-A; +!n('8pGIn7NC2Sӫޢz]SWY|$lh-s:-E E=F2>Ԣhj$;QM~,'z[~JCq%P)γb"{{uI:罃OއbXoSo{id(qcoõjDe{'P RcK-y~_q8uf:*鄶y1S6:BHXL $nx4!ymm*-J?<!MV 1l&=")A+x` pFnL~E};MknSG^yҜq5/qtbH()]{̕ŭq[c>:"=@'*Dt+7@AC6Q!F!זu%*lm(|_X梾|h9J#|JGBUNJR+0>q 1Evǔ2B C[JB読YSFjtc%o>xgoU R{#M-٘K-zů/m8((ۊס!!@]&ߡU#.aד袁Q#$ KQ{%$  9 #(>J=p^ӭXF1w~v`Brh/ |%n@+з 0 va4$/7G;S߾:z YT] ƺJxg#U쪶#[FHQcnHݼIhk&n-24a§A,Dc ]\bxo~Us?r^pXK,ĘPrДi2%1pb[|/~Qv-:( .@A't}Ш/ L٬꧘ /eBֹt?8|{JEP< FrȊ&v\NEz;n%第siy~v=qbAVYgG޻/KA9}Œq4Ƒ[|cS\_åb-n nn,j3 2v#۷U+z|{IM섷x9Ii/RI' O⋠ Z޽.5]p]᪘e)_HH[ 9y:6W{57;Cp/rԱW/2`g.~:%Z4E~VoMV48$R/k?) UzWxr93mW m;8lk̈(~ӷjhTT+h}%wWGC] S0^Fd%1Qo4.6lȅ]-G.fȹohת*uaqЌ@(풬v@ x6E0Ԙ~"ڢ9ǺôEm`L5GMO٦% 4Y#6 Od_s1P3,0bqݶGUffӬV#3~/hvH #Ã,}gpŠ3> EBٽKaIM}+=^qoZ 18cVo>#7MmX">ŞRxQ Ʋ)ugGӰ^rG1&< ܻo[0 k~Ԑ;-*_ nn.*60)O:y3]erݎ|UCXg|g.sY5S h1cNvfP檬8,z~̣l!(Rhu{P 2#u̗y[0{$/c$՝lfT믖`cYyyE1#)A`}/9@# zSfl;0"b+TW]B9Dړn;~PX >UloqCޫU.Z'#u$yI 7#R-7xxr51!gSM첫HAż=s/4F/2ʒKPQn=$ e)N1L@Hd#Sn&}2xAntz4&(9n*Ko7bjOkfv U/3lPH; HDS <&>?.3bmCz 6xX M~Q+/h b2 ,CE*.E6/U֕NgFfdr.&ѭs,V:mY@$'pUZ<=sAki*tU I 4532rHj':ʗPbt鮡AQCX9#aˇg}8R,TuEsƔ@*{jO5zthMq Kܵ< UA7g`!YMKnt6_jMLlwĢtN0Au+;+I;H['ͻy(tF~^:E2nyo;gv(4w_&jfUNB*V坾H;NnpIx֨`9|֗R]1ksu 4O*?!R=;'ĒE/|?bg'a_ [ X"kVR9j/32.%T\v wTIs޿,<졤D$NMFP>* $uYx +\%'KףaQ}EЦ!ku~Gcj֔Ԧ% ˾cTP;үb&=U. GVry _w=ӽ-Nj9{0_D[RIH" ޟMݾd'-}뭏'ZaAg$ U.-CvO܇֎BuXvYqA3jn 眚۫?٤)L;# -K8*J. QpL^;"Պ Tq3"]EvPfk4P}My2\f~|Tb<wt5Z&N{kI`(<##g̲RUaGUoECn`[Է 9e_GX(7fCۇFR2NT,p-F\悩%x#t8ES;~R-iPԿcķvAKHnIcMO\םSi8nfp! J.Nd< ?:qhW"2lSM/ҡ7/ӏ#ĽW$~O.U- }WZ89^T^Clo~[ҘrcRܶruMgLP.cMMI7pgdMC"JVYW=E9?Tht3.K쩲Xv?*ZҾSO9DP {Q 8v*"O+xIz扦s !Ǭ1F:"w~&?Vג[άrNW{Fv$fϸ0ӟƓ_%ôk3u0q L4hIQn Y K1כD ^{j~T{!blf7@if]U\I~f R\(.ޖPcyT{dH' *~fmA a;ȧ|wYCíU#^cTg$b((Й ad>rawG+VRn.6t:v=aŪT A+Y5uujf8j^ ߽sP-w:g)̿]&cYMSfg:ӌ0W ng=DFhfrO :9Msۜ{dJ-"6<䣨.?lK9żbdiVyX$!zU 0&k[~ɸ Q3ZG Yܘ4?} t&m^Sz kܮ {+f"ӹ8JٳR3~C\^^uljVOY#h#h)z' oC?yvߩ'_M-mhʒsYK(? X}\2x?ӛH#1]Jb:H(w|C蓨 rw)&6',g(wh 2Y yH(_ls8wV.0&q%i O1[jx,իDM}8,G _,IBƎBi K$!S WqT(94 6@CT0_ T`}M*SVF\T g䵣UyEHZ$UtR:,s70f/Ŵsp69QDD9 )TM\sy:e;NH_CkB (,:C@]M( <(^)+"L}G1"[Um޶mlE_}4c/io?g]Q$ {[%VX`sfZ|۩TlhۗE2wZ]dڔHCc`': ݲ9DS Q]S6br.E0VDmi8T,ހ\ȞC^޶%B ՠ{MֺuDh!kƯyG}vc^cMWZ(r8 2;\Q> s5.}aKcކ\" o7%`\>Xoӥ^N$EW  R:ׯ^OL޴H[}꟤WaV'kOư_^I*9|_-FU,ZlS٭FkT;y3i4ϸ4D1⤁}./] gzmg٣;!Xj_\[~O2$)4N㶌i tSHU@1Zb# R%qkCXdf@=xi%Xpq]pQ2PnZQ~ 0:I1{>ug6@6Tɻ9C:amXD zʯq0°Stܶz<an+#d߹VNicPOнP= ZP bHbJ^իg/)T!31@= 8Dut)^F[(mwJ8f镎 nZqКjFbLa,6'-H05e tdS dy2VLw֌H0(* ~TiKC]xsJu drV6mgdKl;uM8Djx) /l8^:GglGu*Oxo.TIHTC9u.:QjkFf %bR= 7=xɀyM~r$G8Z~5.SpoU0U0ʟB` g=X;ѽM ^7Rm )>LrTJ P endstream endobj 48 0 obj << /Length1 1587 /Length2 8569 /Length3 0 /Length 9610 /Filter /FlateDecode >> stream xڍP[-LCpk,ww݂wܝ]ɽ3sgomY}ɕTDL& I(đ &`ffcdffEV;Z6PkP?AƎ6qc8y( d `app23Xy;M(B-u[8>_ -O:@dCƎ 7P _4LL...6P{sAZz r;L(ۀfvˮ 5st1 ` 1_P(ڂ @{6F l Bml!n`9 l (J1::!`kc?$E ݞl"o)K@LŠ66  ݘ:Y+70CL~7adˤ9y6frp033sp@v+Ђ7-菓/[-  ` 8;w\ gт4Ѹ33YR-H6[Y'gC򿡚vVd v_@̭=F$dvZ%꿗 )Ao 37 h|s8<+ 8J j{X98n(Bbx<)Ls =/rrD nf+I?o `BYLl@6?3?幎0? dLܑ? o?~k rQg@@J"ImdZy6[tڊtUKn̥M ZĐ8;{X1=db5v~VM/:d휸ѕrq]I,l+E/`W8Ec1M@@D}1uq95D&k#[kʹrC'! [ѝDY2a(s24۾_=,Gd/ߺ\z! K"E ҖrhQ&c1_b\vx^O;ȌM|цW£^'jdx;wJF]UJZƄ_TJjXN$hatBƟ:rFRM~nTHuʭq7xI$ZzҕOl}4 &k`ӻ~;t!u$.h3Źg4wSƿŹ/Z=G e+ D7 >~ ʍR8ρF-;#εodf`~So`K;tfxQתK]83ˌVO^ }TLAgfO0 *; :W]R"my- E.j+䧞S##я?`hYq٨ ,RV,]'C.՜Be*+'x;ӒV//B4U; m]%s,Nk3LE-o`8 ғEIWVtKZR!YPsAڥM,;(RZ(56x6peu5u!c'cY(m7c &Fà:Ѫ QB[Je,ݎ YՐyOu %WJ{ܣLZjTEp_\k]ykhDT ,]t25"ݝA ֧pNwnYGdzo#AX[-}O UgjOGdĦ.J{uF궗ZȦ}#9-Hb,,bβN mIѻt)p|]Hv4~Yj'Z\B6Qa]J!Xku~K8saW^W_g.LB; a|(}MD6ʧ ҳNћTxt (d.X%y΃q9:խ O|93׌u"b93tJG)̈ lΚXCA-ok5F&:M>7";%; ҌR`'a؆Hgɡ~/\zP"1םvF [kփ^7@"BͭV: ~dp}xfOQ- uKe)SFi{p㲛덢g!<&"|47hUP߱ C .Vff1T]Z‚f|Ltrw{M/-/<]b|8ke`ur0jū!@/H"ߦPT^ziSmj/7 8)EuvKS~qm=upWC)oR}w%=*Uvoɾ]D MONNn<"6-لEKsFnk(tG d'?QL9- Z=P˕}܋'A% tHsڟe r1T]7lwnۢsu$a_H0u5κɎުvzDDcRE' .o5~wJ-\!hALiMID$?|΅g+*ӀfQ)p/`1|M1~`bYJ,u^&lC-!2ӋWrgCML2=%O/qՑؠQ0`2h'"up{/)ϧT֘>X2.Π~Mv]p-Uh1byPև~ӢMЭV_ +EY_ c*@Djί^ +\RK zxgkS;SKOǒp\utk)޽ܔ$ ??Uwh| НVW(QdAl 't6HnK$Ka^HQ|ݼH&V<+xW7r %HHe[$OZU [:XlQ)*; h^&/Bj3לT)7(D S<>-9*ՠShL*{ =  U#-Me]U}& BjvȠMnDs]ӯ]JBҋ%Xx+=ƴ-wi'&c{|#DRX)ѷN<5W*u6YkgXgAe&_&!-?ʪ/`!3Jbx Ϋ֎n/Dy ^D [Y'A az̝t4yenF*n՞JL7iv F,| '^Le }#7l0'ZE)xUܨNŬ6Md񦄒F;XnCQRrڃv'?E&g3 ˰jWfayKC0?t!^UJd_UmeŸldR$䮄+Rݫ__ l 9RI&r\3|vzJm!?hEe_F.#I[@y]udNU`|9̏[l% GQH b6ff06NŭXȏk7+ӷY%S'~ߢTF// T) UI .Dc+\Xx3%뿿(BO'Ԍ줠QD!b ߠJB[i1CЖ[qε1̜* Rzx#.ڐdo=K 3d̝ڽy|uF3Jey"DV:c"po|1.ICy.l/Ӱv:O\51?Vj'E~HvUʮr*QYhv,"[,_O"f߻^Wb Ĉ/ZCԝ\ RT旉Tx@EcPk1[u]ιfh6L<ߟ\=˄y+ $=mf5OP%(' #VApQA,lmOTO`FzMg%c&02v̽ 2izE[GVeR~$}`̳k4*7/|z`YOluō_ő&hpx0}xۤ3:Y1o͚JL5ҫsem5SY/D{fKQy\X{o|\Gw$#LPȷ%vH)BWP6Q2FlqGy@G:nx9V+;?-q5B"nCWU?\tmF")D} P1~NS1WH< b7W:%[uEPF+#59f\‹° LSrqaM]n]>e3x;یL& $R-x<37bZV?+T+w]3425gx8#yh]sߺYMC|[@_BڹR8ojec2J D]#'AͮH@&3i\yh3v4\*DIq]a 9on|1w_)DfqFn+:O>g>!6\gRE_wobCn/'.VZn~k6%$#6n}O};9k*ï/nB 7OjV Vk(T|Q@~J c'`,SQ{xzjT'OTmBOGCƬбv.BQ|w9auo\m.ʾ!]®# geJLCUTk̪kB&u>R1{@#h a3ѕMjY2GǫyZlSFNf0]N=|<b 8u~8YfQP6ƹߍl(=ʮD+icspD!P{?tAFmk*je$3ҢA+ C3fC3r~4Gk8)G-̛Ga.Hb~s@S߀|Kؑ^c0&Ε0vQy0~_w x?*Ú4^0cVO'љ- cqE'wcZ2vkd-j5i'|e}@3k;<<8,VJ w. j  K ^ ?ImOG9_#wX@zef3x۩lWWTgr˸߇-̀*DWC܌kPT0g":^:j u9-BjSࢵ/ɠ+xW[zAx5>_ݲlT1B돍?iZKU;K}ݐL8.GHߺPq2n$πG+Tcm"BIm\커VTDZ& z/Z-593C(A|Ѵ[Sq1~9$1\HùS6j` `|-*~Bԓ~6Hf7{=;Q=U6[jW Ϝh[m@K*Vܺ0V5 ASw 2$d:nE/( R`\_K|D)*0hh  ]2 DK1%Q,3UjC|[j$'NѺxMJĸk4+YS.V Uï$KsN & DYx+}5q:@@ĩ]lvG'3HCz@L*]\FfJ1a$}ΔԓEôxQ).njWfߴPK3 E}=t0Qh1 4٩!lq9GyyHj"~e0O.6J8 CCWc{>4tE]Cr7f^=E4"M~!ܶ> stream xڌtk Gؚض۶3Fƶƍըqz9=}kf QRe6s0J8ػ202DXl̬jV)4.Vb:]A21cWQ f `app23XyGtp[2@x QG/g+ KWP}PXxx4LƮ@;PDSc[?.-]]y<<<\-><\-*@; Gc;ߥ1S,\R:z; )dfotT@r7򏻿pdePcttۛA4uq[n V*>Sg+GWF+?jd fvv@{W?rpm<}̭(͑I (-7$-8X@'Ԓj^?,A58:8Aéxcw o< `$Aw2֏o 3sMsL2tRD``ecpq8y8~dlw7w,KK xK@5c`6^?M^_f$fk/oho\Ag@t/UY_1,[H+ +O埻XsfkeTrpf003pڀnJ#ۛ:qX98^̠MbN%01;L$/ `L7I70Lh#PA7T@>A J+I7EPLj(?TobZYZ9#ggCo2(9D116q5v-eIAb b[T?42aCbg;?j,ea%oJ_DehvP--bdV 5wY@oW S{K*wtԠAA5̃oj#hwA;9LU H~mJhgrk '.kؠ_,,  @\-\W|^7P?.h =~CVSAPTAP t+\MnΠ[= |!_B:=v'f)v5h|;äfm8 S5„MRn}6LPm_*:n$#`P}qlsr~T~1 0X:W)\!V=F/t"${ڕyv-wX&$Gg5a{JեWm|G OYĬb3 # X7)4628_{SV?"\֮#8t%{pwtf0 ^>{[P77ǧ_tGuͷ1ZD^0 {|3}Ng=!kXdJfAXqԜNv֖TM(()m~/CEEIXźcy}wH1??#X:ژD(VgQ`<^J Z˖7GN|WU jyC*'OZ֯#OיY^-PRL7a,i<)A{߃_WFw͂5dlʘqӺ^GȬ|,]<֞vM*5$F]O>b=B|GL]Sӌ*P?Fd lo (5׿I ୟUf7v̧} +R^RTz)Fj*L>K}ƞ֍[%qG!ǷvO"%[Q<.GXvfSpys7$9٬GF?4f Z^Gdm.B EBC3#yQH.i}gΆʏc̱*Ś\QRJ28&:>78zKFFScvS_8ƒ*>e@i g˾',Z }֞|vVnm:.UcChq mwG쭻X;L1>y >ߏJgEz~d_v{tQTfnqBouAHDMS?eG*0[blujgϏN:@da6k)Tpo/\h7Oa}f$"258ֳ4GG 3Mq *SU%ߩdVBr] n ~9&_Fs$Zj2UdP9q\-?,eK* 9D&ld8iEc#"FY*hGBY*dY$YJ >Ql*8r7 bVn>J`1:YϽ| 2(_VQw(5ΐ穇i!căd;qe pT{2XXIG|$r(>MK>D5xJ{HΉ˸<#ۅuUc{jJm<2wjF'>!8'V<ݞR s잆Dy_2sJͶm9LL֝?K2t$/8M|_Ox:3c`q8 yx?닟r, 3aiB#A*bNӘ./eZRn\yp%aO$PW6GC'VDWace8aJ@ F20$=C i \R'ak1H|_?VL#|at&tJX| es>~7uA!M.Ef]6sgfȫ6ǡק%n4'1Ύ8S/If!H2oL-YRT]:!`KEܱEqC:(qE\>r?P4h(ѶlF؂CNE?9;cW.Il%|4ru` *?|9^57˜xJGmX\DC)4݁XDFз?;{ac9Hnw'\''a*Z 0['Yb2K4 U”-i!)A sF{I"Snl "DV{nwP3L2y%) j &^z2.z~7t3mF'WvZH-r,đL )~ʻQI˘޼ɞIJ0u$]ra IϼD|57oZ!7PK&#<;f"D 2* j$Y3^`FTM/ԐհJdC j1PWRDoerGa`P4ܔL"(H2G4FCj1{wlsc=joXZmsqwrjnm~Mce;čIݵq,?h̞ɮF':G.ڰT_SRJC' ff'NM?/rJNX?*o?mQI5 B"Ȼy˕Km."$J띑 nXҤ> BZ3<† (px}2 l4Z7r^Et'@z/}rf6EH5ή6P#ꛙEwQXSPU%kl<3-Lr`y{*c!R)+?`}`pIc8aPv?U*ImMej7@" #`\EN x~XjR) mܞQ!?q58b&3$@7qݝ2nHCQ! CvX$ ]Ղeߊ>=\qO$uTƳ!{qxV`u[gmM3Ⰽ7"9Oo>(LA5z2%Oڦ Bû.EN=FM KFj4M}M mLƓh329,AtaAtLqg]m-ӳ΍g ڵSfBE0R.AO7kCGL_m4,~~L~ɏ^Gn2+Pm(ƅ9ۋy?sKfcf>dqQ5|*ؤxF(l 9dGz$I-5Z|()@d;R< !۳<] {}֦UIF-pI_.Z>%+~W^{Baڅab_6ܲ&9qLtP3P ٢4 A7Ⳬb}n::z!L&5NWS!hZJnDh/|Lpo4I3:8v;ƝT(pqۚGAZ]G:2^RO9"9^Z E{*n̑l<0*>P,@NXG*+c!>Al-iIwϤ֙IZ,w |T7e JϮ>>rH Q ?O ™VYq;k(b2Taaٞ_0s:4*xi! C9O[FV7a0kN8LEiFƊNS |7QbDPxŰnBwɩorZH+?Ēw?9w/& >uU&r`4@}bе (YATj%pfMEdW gIV&ՇnaKKwzڇ+l|H ߕ]rz;&aV@I^RW3Nȭ0̜-i{=*1sMfg^xQvcXPYDF,_}ܥ}Ԡ5<$Bݚ-+*z]Y|9%sRUfB(Ӝ? C y\yTTiXҿXȲdx~QKC-6MiEPʪ1$4TM [3M -m8t1~67 80t<AWca3!΍"ddd]?}jY:Gͤ; 'Zo̹3uJ!u|mTo$c(RIdY:tq΍H7x9 v[N~Iwr,nlzC+Ǽ%[b|oJ y%c9ゃ̪ՂptNuAMk2GQm| 8{ |(idlYǭ$O,)m8;Ļ!`Y9˦<QL8uqВS f@D-u]m. u[I9+Bb/'>EQwRX ‚<sƉ8>cQͷ~r{n%qWs5t7 CM]o+?16,|5yYϟ~rֺ5p0vyxpgNS iIkshtB @_3N;̐97D[4i uDG2sT㱿M.|U Lc Zfͤnan Jl S묘@- gƹC_cña*pC |5i!{{f[%|LMX0Lsny&eRRgk#4NFqQ5Xjށ7o Ԍ~c{Y̬.d+W|3`%!~%^F˴YVQANV70B@aNmJtOƢƏNyG 8녍ͤ PIV̶Cl2?J[boss/(65gE]RH(L*¹ {Vbu|09e[Z݄oN[p=uk|KANHvδQ? VssC>tQK!v`1;Q+O ^ 5_.} x7r !.n꬟(ȗh>EJzɧ*5F))0Ķunpj;>5JGzIO093SK(eAv碯BݪYRe? {ȊM(M _OdgMCf/5qYuZu(rm(\䘜peyA&[, IO@R {y`BW%{`-3Q~qKBZ2gֶt;6冃:S fd7}^9Ӛx B`ibCve k791Ү י6 cƋ+>z>qW¶8à݊xge酤jb; kMInN<х :J510<6`(Lމ(skQa1)Aswa:E\147U0@cwa!]Y6E Tk9^ƽdȴJqY!εkHEf,guuWiiɛ MOo 3EcoWE$r<<3C~ջbTlGEɼMh%>R h%Tdj>WP \7łk>$L8"ێ:ӞDBp-ǁP_{kfF&N*E~ƅ5C,_ W m(ƆwI3Ob{4ХXO)fAldg}>WMNDT@'n>Ǐח(Qew\WSKfֽ+ {dMb:yG:%# .Eʌp>|C>+Z7!^-ե}UC̀M5dOEjf/qs"1ݺKY׽q#NfMȯeyI=n86֟s 2*Jזa]$Bf5⬁Hm0\p9|m$,x OLu6XRWێ:]u製2~XTOѸmVv#䮴0ac-3^pJYlft F9f )`'÷:1|/ÖQyoIHQO<+d=)[AGuvg0l9ߍu׶1MW{f7<ngGՐm: J2Z͉E2' ;#y*ía3?(߈t+.D;^9mx~-;h_f EcIs8ޛ-gyn~*^4z|i8cnx|.%00 &[p\žOkݙBZ\u.HG:$uؓȻ|Qz Ia&J90fHtٸ삆B]R"'fsjBX*#'@o}q9dJq.Hu<`%bgR ~==ɏM>W)g3Bn(KZɡC٣nӆ64iڄAgD2m 1msAJ0bOs=iy t]n%i6]&͵ˏ˃ 2W'es,\aKG1s`3A"2y E{ #@1e~WZYdP9]U_,𠭐c0}+V^y!>m'(-WB^q/(BJ6ONPP4tش$h{{CBcI=)6ȔRvC_'ǹ&Iqx)>"=5 z:Uf1Z X8YT;!ۼS”Ui T(qRޥ`pey¾ӥg͟/UQ1H~߂;(e:MmPcۇ=X-r{]K$yliҦ_#WƠXo u{.F!qKlbHyGW@|~hsO|b_B;'e3eq:H nGrёE=1WbipxW(iF{ *[@qP7ep'6N%Ln Q^a$yE$[UdYcO[9c8bwcA!E4AZl=Ck @?WsjS;^5o82kzCD ;f?xs }X$$70F(9xڼ,LZ+~9;)њ.njR'xӐm 8fqJ ;B[ul7F',RJOg܏ֺ!Hs&Wk\]Cy S&(|Tg{?rPTqT*/;Jk`Ća'')_!jit)Ll2h^Zq8 lf4MN8ʖ&KJEig۟sc>p,ITi$P!T$,=KVl^p?~<~97u8zaoǹiLxL+A|S8[A jI&&W,㹗J=vIB=:(mU/eAd?]R)[2b,A'r7鰙حa[5UJfMo!/'bwۥf%8T<)$ÕhQQY=5$Ey}45 ]jh lqM >My=)wE<=¡pONNuА;Ƴȋ.vJ#L>l:E g>1{Ӌ@Wi5Spţ Fc 0ְP$i29cP&WJ]\u2ǸzZ,kVnHm;LCl0[4Y0񏝟"M#\x~)oԬzзX'gd"~=Y~+ҟ+WmUj6<SNO1Hogr 'p r".aϾ3\]ushznE !!Yj߄bj0_^}nb)QFb1ұ [yÁi:hW͐ .6Ћ=[3_cފʃʕCߚ5`w"&yK[\@L^Bc|@jqDTvU/^c~w+{/GaxlX {h:E*rFZR|\J gmqc0z+)|UҴH8"32t9n(ɷO]մ޾J؍џɂ<{EN.ő ^P+Z#;{7 O܀vD_$ɀ@Jݧ{"~F 9ǫAξ3uэWwmqP #?yѰ~0u2xsH *°6r80qjӑsa1DJ5b?X!^ .8lfu2dvW/>jHdȗO0έ;^Cwsе;&ሻeE9X)׈cݐBEIa6Hhc7fؾ.nib]%y,*v69k8{dCOYhϖSI5;YX>`a=P{ >0^*aDVT" n%Dsc8G\Zb_eژ|Q}` /٬mǍ'!Eaq9ׇ̮Bt $cjg@shszl'|ff!]3&sjF($e4&g" ^;$"V᱖=T{;tjnyM~69p(eDl?ցEOyoە:iX}ynar^DJ`kR}' NMku ֿZRxC7kqCС:&-K^ߒ\K!-oz/x0F!5,L0H8 M+1򎜴j|e{חϞqI4Y(1WFjugDeAs#W蔂8>2k2EJc9O})zKδ4TO M a~7=Ig8M!f1S%q} R*hAPHY((ϗ6"ٻRi)ut~s 9Lيdт7ng@+dv;#rӧc/GV =X 1cېJH8W{}kَKz\F:YU{RyNKIԖ GswjvQ, `Zn/ߊy#enu8oeQJzHuŔ~YdR^+^/9+R'ªJte~0n! l 2Ki֫Ȇh^C %&6ÒJJ/ӅUuB\T|.F=HXZqܯY sqG!q$q2dB [#e$Fی'NڔĜxup%g:RI~Vr}hv4`d `P9huQ^ؿ Yv; 22,z=D2N9YhwFz.ȸM͢#ޮ Ǩ?3*iwĝ[MVq;NTc0Dh'pcw -gLO҅ ^fk+v <<lp aǕޣΈF85lR9hmM/G$^/$;w,] [=8y7/=9_]SZq#M!Hў*΅-c Z&.7wƼ$l#w?: I>'Vc@C܀Sк\1Z*z5ɿԽyOoPNHc9čeZ((TUFTb F.KR@ס>~T.IDTBə W,I7K`[h?cg3=1a娜|xVtgIi3ϖ~o]{uAuٓmZbAf VHTvs4/ǬWnt琮?P/ :%Tb}'Gk (&ƄC|cf ]ѩߘGy_w4rB.Ԕ"~(,1- ;L5uބ`^iCtjuEs^>i]~!^ /tv8^ϳEچc>NY*v ϊ enOz'k vƧV P_K弫%/ϴ7JUV7,gp&X| |DO~8QQꣽlo}J؆(F7*PXo`tzmy͸%3#T^dOOybyA;|!91^4pK* ͡:+2砝뫄s[ ryJnpI()AشWzI*JΦF0/':P?yֽg}gU.:ELdLSI 00yhztRO )? pc=>~!ο;e@tY0l'>%~.Lh'N6c66#qbϐVi$bcww,Ar(jC!Qłǣ&5LY_`S|:?MV!t- o?YQvU'ٴu LeUj*˅Kދb<)ǵ_ˏ^"־_ӧZN OS,ݐD?#IRZ;<+TwA8yT)D١Mqu34秲/AO j=;1 ;:Ԉ7ZfX{==N,w/n|1DⳂRQX[ *9omz?ZT` 8^vm d/ti=6v9*ݞ'P%؝~fŠ·[*#Aj7 d̸coʦ4GY*;)fؕv}'u̥} XqЅ$`9%νy>/R)qHQPqfĺf1OR8IdOtY2j;AQS*&B#| xʅ.X y2hqFسL:~x_\M? 2>Vwo48> _.4j[E;Y9 9]^b[=ZZRĢBV* iޱn ?掱lF^VTg7D7r>XZ@;+&L 1{{+u:yGv1FJ: EC_xdIkUCm>y\J'x2̎oҤ 8:o{hNQuiEA/{9;5i5r>LV|w\VaNʷBQT/ؕ_ZJ$(k %߃ ),ڏVzlb&~!#Air"KJLQFeM~QWR :BoyuTo`*o q)ˣk'"ҝ4y;G|qp8)78 K' }YΉ$N'\revuO}eq?^9aʥf77jbx[$SS171 XJ *;\&C` endstream endobj 57 0 obj << /Author()/Title()/Subject()/Creator(LaTeX with hyperref package)/Producer(pdfTeX-1.40.17)/Keywords() /CreationDate (D:20171003062259-05'00') /ModDate (D:20171003062259-05'00') /Trapped /False /PTEX.Fullbanner (This is pdfTeX, Version 3.14159265-2.6-1.40.17 (TeX Live 2016/Debian) kpathsea version 6.2.2) >> endobj 2 0 obj << /Type /ObjStm /N 44 /First 326 /Length 1860 /Filter /FlateDecode >> stream xXr8}W1ޭĕDTgēd&-6+!_{dzU6Kƅ,a),2c)D3ͤ`J &2u„a:uL fIŬ1cA:aRLZ91%(B2kRؑLhm25)x#C.dE 9N1x&SkNR *IF:*#҉5C*'p$L0t#Q)טƐVcO3?b 1~\/wM1ղ-m ɍYTzZ4w2?eLq'#h1$h`k 6l'KO&ߒŽMjwcEvj)Ʊ*"73bh%9:fkYg^D:M'&q[;PRCX2y,)+bB}?OFUPӂ*ۃӼK1N^> R(VNCN]gݴy]Ư嬽q|VryCLJ AAɼj=}Cc\qtjLOЋt,1tJfw3N4XDƙ$RlWK J#J+L $k0 Sr$ڻj/떜R }0'ʭ2[ }%[@D'-99)6 {2P뙓4%n7Džն*K_F1iNSʍ7CzRENEO lKfbSQ!)}4Ǫ[&īt v mԄplkҹq}Ùo~F'6A wC}; u_">T8 cCtҍ^SiS:֯hK$7YEI%IF"j#fxg:ZE Ѧ/,c-<6Y_͸/L !Ĺ?XPƹ}^FC NУ媭pbYJ\$hyLNm ZWQܢYYEÕ'm>/˛y-($Jd|Η oKhҲ³O_CBh]}_eۺ@gO?ӏe߃<!s+s;|iX|^J q^H!.\,#gw鲏ՇGo>zR!>S.]FJv"ރyty_A=*1N_|H/.L| Ul;H!R>>0& _9ϛiYNz^"Oȝ|-Q-yqn5mkV!j=L _VHm-K$^L?oׂ]c.`-}۴(6 LCRmvm7mm-~`M7bh\[JŠ'5La7{]Κ͛[|2#<t`³jvHg+h=f{MGϷ۶cRz^kmGS.v`j#;M1mjr@Gmz?/ک̘a_yutY9s(bh촚}S]sl_UXXPVd endstream endobj 58 0 obj << /Type /XRef /Index [0 59] /Size 59 /W [1 2 1] /Root 56 0 R /Info 57 0 R /ID [<354BCC1F2694C17F5B330B9FD456781F> <354BCC1F2694C17F5B330B9FD456781F>] /Length 149 /Filter /FlateDecode >> stream xQ`1};#%gHQM{':1 c̑CF"vy!T?]48ڿZC 4Bt&ku:KF/S˭ endstream endobj startxref 64990 %%EOF RProtoBuf/inst/doc/RProtoBuf-paper.Rnw0000644000176200001440000017477613005133352017356 0ustar liggesusers\documentclass[article,nojss]{jss} %\VignetteIndexEntry{RProtoBuf-paper} %\VignetteKeywords{RProtoBuf, Protocol Buffers, package} %\VignetteDepends{RProtoBuf} \usepackage{thumbpdf,listings,booktabs} \graphicspath{{figures/}} \shortcites{sciencecloud,janus,dremel,nlme} \DefineVerbatimEnvironment{example}{Verbatim}{} % Line numbers for drafts. %\usepackage[switch, modulo]{lineno} %\linenumbers %%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Spelling Standardization: % Protocol Buffers, not protocol buffers % large-scale, not large scale % Oxford comma: foo, bar, and baz. % Articles with many authors we should shorten to FirstAuthor, et al. \author{Dirk Eddelbuettel\\Debian Project \And Murray Stokely\\Google, Inc \And Jeroen Ooms\\University of California,\\Los Angeles} \Plainauthor{Dirk Eddelbuettel, Murray Stokely, Jeroen Ooms} \title{\pkg{RProtoBuf}: Efficient Cross-Language Data Serialization in \proglang{R}} \Plaintitle{RProtoBuf: Efficient Cross-Language Data Serialization in R} \Shorttitle{\pkg{RProtoBuf}: Protocol Buffers in \proglang{R}} %% an abstract and keywords \Abstract{ Modern data collection and analysis pipelines often involve a sophisticated mix of applications written in general purpose and specialized programming languages. Many formats commonly used to import and export data between different programs or systems, such as CSV or JSON, are verbose, inefficient, not type-safe, or tied to a specific programming language. Protocol Buffers are a popular method of serializing structured data between applications -- while remaining independent of programming languages or operating systems. They offer a unique combination of features, performance, and maturity that seems particularly well suited for data-driven applications and numerical computing. The \pkg{RProtoBuf} package provides a complete interface to Protocol Buffers from the \proglang{R} environment for statistical computing. This paper outlines the general class of data serialization requirements for statistical computing, describes the implementation of the \pkg{RProtoBuf} package, and illustrates its use with example applications in large-scale data collection pipelines and web services. } \Keywords{\proglang{R}, \pkg{Rcpp}, Protocol Buffers, serialization, cross-platform} \Plainkeywords{R, Rcpp, Protocol Buffers, serialization, cross-platform} \Volume{71} \Issue{2} \Month{July} \Year{2016} \Submitdate{2014-02-05} \Acceptdate{2015-04-13} %\DOI{10.18637/jss.v071.i02} %% The address of (at least) one author should be given %% in the following format: \Address{ Dirk Eddelbuettel \\ Debian Project \\ River Forest, IL, United States of America\\ E-mail: \email{edd@debian.org}\\ URL: \url{http://dirk.eddelbuettel.com/}\\ Murray Stokely\\ Google, Inc.\\ 1600 Amphitheatre Parkway\\ Mountain View, CA, United States of America\\ E-mail: \email{murray@stokely.org}\\ URL: \url{http://www.stokely.org/}\\ Jeroen Ooms\\ UCLA Department of Statistics\\ University of California, Los Angeles\\ Los Angeles, CA, United States of America\\ E-mail: \email{jeroen.ooms@stat.ucla.edu}\\ URL: \url{https://jeroenooms.github.io/} } %% It is also possible to add a telephone and fax number %% before the e-mail in the following format: %% Telephone: +43/512/507-7103 %% Fax: +43/512/507-2851 %% for those who use Sweave please include the following line (with % symbols): %% need no \usepackage{Sweave.sty} %% end of declarations %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% <>= library(RProtoBuf) rprotobuf.version <- packageDescription("RProtoBuf")$Version rprotobuf.date <- packageDescription("RProtoBuf")$Date now.date <- strftime(Sys.Date(), "%B %d, %Y") @ \begin{document} \SweaveOpts{concordance=FALSE,prefix.string=figures/fig} %% include your article here, just as usual %% Note that you should use the \pkg{}, \proglang{} and \code{} commands. % We don't want a left margin for Sinput or Soutput for our table 1. %\DefineVerbatimEnvironment{Sinput}{Verbatim} {xleftmargin=0em} %\DefineVerbatimEnvironment{Soutput}{Verbatim}{xleftmargin=0em} %\DefineVerbatimEnvironment{Scode}{Verbatim}{xleftmargin=2em} % Setting the topsep to 0 reduces spacing from input to output and % improves table 1. \fvset{listparameters={\setlength{\topsep}{0pt}}} \renewenvironment{Schunk}{\vspace{\topsep}}{\vspace{\topsep}} %% DE: I tend to have wider option(width=...) so this %% guarantees better line breaks <>= ## cf http://www.jstatsoft.org/style#q12 options(prompt = "R> ", continue = "+ ", width = 70, useFancyQuotes = FALSE, digits = 4) @ \maketitle \section{Introduction} Modern data collection and analysis pipelines increasingly involve collections of decoupled components in order to better manage software complexity through reusability, modularity, and fault isolation \citep{Wegiel:2010:CTT:1932682.1869479}. These pipelines are frequently built using different programming languages for the different phases of data analysis -- collection, cleaning, modeling, analysis, post-processing, and presentation -- in order to take advantage of the unique combination of performance, speed of development, and library support offered by different environments and languages. Each stage of such a data analysis pipeline may produce intermediate results that need to be stored in a file, or sent over the network for further processing. Given these requirements, how do we safely and efficiently share intermediate results between different applications, possibly written in different languages, and possibly running on different computer systems? In computer programming, \emph{serialization} is the process of translating data structures, variables, and session states into a format that can be stored or transmitted and then later reconstructed in the original form \citep{clinec++}. Programming languages such as \proglang{R} \citep{r}, \proglang{Julia} \citep{julia}, \proglang{Java}, and \proglang{Python} \citep{python} include built-in support for serialization, but the default formats are usually language-specific and thereby lock the user into a single environment. Data analysts and researchers often use character-separated text formats such as CSV \citep{shafranovich2005common} to export and import data. However, anyone who has ever used CSV files will have noticed that this method has many limitations: It is restricted to tabular data, lacks type-safety, and has limited precision for numeric values. Moreover, ambiguities in the format itself frequently cause problems. For example, conventions on which characters are used as separator or decimal point vary by country. \emph{Extensible markup language} (XML) is a well-established and widely-supported format with the ability to define just about any arbitrarily complex schema \citep{nolan2013xml}. However, it pays for this complexity with comparatively large and verbose messages, and added complexity at the parsing side (these problems are somewhat mitigated by the availability of mature libraries and parsers). Because XML is text-based and has no native notion of numeric types or arrays, it is usually not a very practical format to store numeric data sets as they appear in statistical applications. A more modern format is \emph{\proglang{JavaScript} object notation} (JSON), which is derived from the object literals of \proglang{JavaScript}, and already widely-used on the world wide web. Several \proglang{R} packages implement functions to parse and generate JSON data from \proglang{R} objects \citep{rjson,RJSONIO,jsonlite}. JSON natively supports arrays and four primitive types: numbers, strings, booleans, and null. However, as it also is a text-based format, numbers are stored in human-readable decimal notation which is inefficient and leads to loss of type (double versus integer) and precision. A number of binary formats based on JSON have been proposed that reduce the parsing cost and improve efficiency, but these formats are not widely supported. Furthermore, such formats lack a separate schema for the serialized data and thus still duplicate field names with each message sent over the network or stored in a file. Once the data serialization needs of an application become complex enough, developers typically benefit from the use of an \emph{interface description language}, or \emph{IDL}. IDLs like Protocol Buffers \citep{protobuf}, Apache Thrift \citep{Apache:Thrift}, and Apache Avro \citep{Apache:Avro} provide a compact well-documented schema for cross-language data structures and efficient binary interchange formats. Since the schema is provided separately from the data, the data can be efficiently encoded to minimize storage costs when compared with simple ``schema-less'' binary interchange formats. %Many sources compare data serialization formats %and show Protocol Buffers perform favorably to the alternatives; see %\citet{Sumaray:2012:CDS:2184751.2184810} for one such comparison. Protocol Buffers perform well in the comparison of such formats by \citet{Sumaray:2012:CDS:2184751.2184810}. This paper describes an \proglang{R} interface to Protocol Buffers, and is organized as follows. Section~\ref{sec:protobuf} provides a general high-level overview of Protocol Buffers as well as a basic motivation for their use. Section~\ref{sec:rprotobuf-basic} describes the interactive \proglang{R} interface provided by the \pkg{RProtoBuf} package, and introduces the two main abstractions: \emph{Messages} and \emph{Descriptors}. Section~\ref{sec:rprotobuf-classes} details the implementation of the main \proglang{S}4 classes and methods. Section~\ref{sec:types} describes the challenges of type coercion between \proglang{R} and other languages. Section~\ref{sec:evaluation} introduces a general \proglang{R} language schema for serializing arbitrary \proglang{R} objects and compares it to the serialization capabilities built directly into \proglang{R}. Sections~\ref{sec:mapreduce} and \ref{sec:opencpu} provide real-world use cases of \pkg{RProtoBuf} in MapReduce and web service environments, respectively, before Section~\ref{sec:summary} concludes. \makeatletter \if@nojss This vignette corresponds to the paper published in the \textsl{Journal of Statistical Software}. For citations, please see the output of \proglang{R} function \texttt{citation("RProtoBuf")}. This version corresponds to \pkg{RProtoBuf} version \Sexpr{rprotobuf.version} and was typeset on \Sexpr{now.date}. \fi \makeatother \section{Protocol Buffers} \label{sec:protobuf} Protocol Buffers are a modern, language-neutral, platform-neutral, extensible mechanism for sharing and storing structured data. Some of their features, particularly in the context of data analysis, are: % \begin{itemize} \item \emph{Portable}: Enable users to send and receive data between applications as well as different computers or operating systems. \item \emph{Efficient}: Data is serialized into a compact binary representation for transmission or storage. \item \emph{Extensible}: New fields can be added to Protocol Buffer schemas in a forward-compatible way that does not break older applications. \item \emph{Stable}: Protocol Buffers have been in wide use for over a decade. \end{itemize} % \begin{figure}[t!] \centering \includegraphics[width=0.9\textwidth]{protobuf-distributed-system-crop.pdf} \caption{Example usage of Protocol Buffers.} \label{fig:protobuf-distributed-usecase} \end{figure} % Figure~\ref{fig:protobuf-distributed-usecase} illustrates an example communication work flow with Protocol Buffers and an interactive \proglang{R} session. Common use cases include populating a request remote-procedure call (RPC) Protocol Buffer in \proglang{R} that is then serialized and sent over the network to a remote server. The server deserializes the message, acts on the request, and responds with a new Protocol Buffer over the network. The key difference to, say, a request to an \pkg{Rserve} \citep{Urbanek:2003:Rserve,CRAN:Rserve} instance is that the remote server may be implemented in any language. %, with no dependence on \proglang{R}. While traditional IDLs have at times been criticized for code bloat and complexity, Protocol Buffers are based on a simple list and records model that is flexible and easy to use. The schema for structured Protocol Buffer data is defined in \code{.proto} files, which may contain one or more message types. Each message type has one or more fields. A field is specified with a unique number (called a \emph{tag number}), a name, a value type, and a field rule specifying whether the field is optional, required, or repeated. The supported value types are numbers, enumerations, booleans, strings, raw bytes, or other nested message types. The \code{.proto} file syntax for defining the structure of Protocol Buffer data is described comprehensively on Google Code at \url{http://code.google.com/apis/protocolbuffers/docs/proto.html}. Table~\ref{tab:proto} shows an example \code{.proto} file that defines the \code{tutorial.Person} type\footnote{The compound name \code{tutorial.Person} in \proglang{R} is derived from the name of the message (\emph{Person}) and the name of the package defined at the top of the \code{.proto} file in which it is defined (\emph{tutorial}).}. The \proglang{R} code in the right column shows an example of creating a new message of this type and populating its fields. \noindent \begin{table}[t!] \begin{tabular}{p{0.45\textwidth}p{0.5\textwidth}} \toprule Schema : \code{addressbook.proto} & Example \proglang{R} session\\ \cmidrule{1-2} \begin{minipage}{.40\textwidth} \vspace{2mm} \begin{example} package tutorial; message Person { required string name = 1; required int32 id = 2; optional string email = 3; enum PhoneType { MOBILE = 0; HOME = 1; WORK = 2; } message PhoneNumber { required string number = 1; optional PhoneType type = 2; } repeated PhoneNumber phone = 4; } \end{example} \vspace{2mm} \end{minipage} & \begin{minipage}{.55\textwidth} <>= library("RProtoBuf") p <- new(tutorial.Person, id=1, name="Dirk") p$name p$name <- "Murray" cat(as.character(p)) serialize(p, NULL) class(p) @ \end{minipage} \\ \bottomrule \end{tabular} \caption{The schema representation from a \code{.proto} file for the \code{tutorial.Person} class (left) and simple \proglang{R} code for creating an object of this class and accessing its fields (right).} \label{tab:proto} \end{table} For added speed and efficiency, the \proglang{C++}, \proglang{Java}, and \proglang{Python} bindings to Protocol Buffers are used with a compiler that translates a Protocol Buffer schema description file (ending in \code{.proto}) into language-specific classes that can be used to create, read, write, and manipulate Protocol Buffer messages. The \proglang{R} interface, in contrast, uses a reflection-based API that makes some operations slightly slower but which is much more convenient for interactive data analysis. All messages in \proglang{R} have a single class structure, but different accessor methods are created at runtime based on the named fields of the specified message type, as described in the next section. \section{Basic usage: Messages and descriptors} \label{sec:rprotobuf-basic} This section describes how to use the \proglang{R} API to create and manipulate Protocol Buffer messages in \proglang{R}, and how to read and write the binary representation of the message (often called the \emph{payload}) to files and arbitrary binary \proglang{R} connections. The two fundamental building blocks of Protocol Buffers are \emph{Messages} and \emph{Descriptors}. Messages provide a common abstract encapsulation of structured data fields of the type specified in a Message Descriptor. Message Descriptors are defined in \code{.proto} files and define a schema for a particular named class of messages. \subsection[Importing Message Descriptors from .proto files]{Importing Message Descriptors from \code{.proto} files} To create or parse a Protocol Buffer message, one must first read in the Message Descriptor (\emph{message type}) from a \code{.proto} file. A small number of message types are imported when the package is first loaded, including the \code{tutorial.Person} type we saw in the last section. All other types must be imported from \code{.proto} files using the \code{readProtoFiles} function, which can either import a single file, all files in a directory, or every \code{.proto} file provided by a particular \proglang{R} package. After importing proto files, the corresponding Message Descriptors are available by name from the \code{RProtoBuf:DescriptorPool} environment in the \proglang{R} search path. This environment is implemented with the user-defined tables framework from the \pkg{RObjectTables} package available from the OmegaHat project \citep{RObjectTables}. Instead of being associated with a static hash table, this environment dynamically queries the in-memory database of loaded descriptors during normal variable lookup. This allows new descriptors to be parsed from \code{.proto} files and added to the global namespace.\footnote{Note that there is a significant performance overhead with this \pkg{RObjectTables} implementation. Because the table is on the search path and is not cacheable, lookups of symbols that are behind it in the search path cannot be added to the global object cache, and \proglang{R} must perform an expensive lookup through all of the attached environments and the Protocol Buffer definitions to find common symbols (most notably those in base) from the global environment. Fortunately, proper use of namespaces and package imports reduces the impact of this for code in packages.} \subsection*{Creating, accessing, and modifying messages.} New messages are created with the \code{new} function which accepts a Message Descriptor and optionally a list of ``name = value'' pairs to set in the message. %The objects contained in the special environment are %descriptors for their associated message types. Descriptors will be %discussed in detail in another part of this document, but for the %purpose of this section, descriptors are just used with the \code{new} %function to create messages. <<>>= p <- new(tutorial.Person, name = "Murray", id = 1) @ % \subsection*{Access and modify fields of a message} Once the message is created, its fields can be queried and modified using the dollar operator of \proglang{R}, making Protocol Buffer messages seem like lists. <<>>= p$name p$id p$email <- "murray@stokely.org" @ As opposed to \proglang{R} lists, no partial matching is performed and the name must be given entirely. The \verb|[[| operator can also be used to query and set fields of a message, supplying either their name or their tag number: <<>>= p[["name"]] <- "Murray Stokely" p[[ 2 ]] <- 3 p[["email"]] @ Protocol Buffers include a 64-bit integer type, but \proglang{R} lacks native 64-bit integer support. A workaround is available and described in Section~\ref{sec:int64} for working with large integer values. \subsection*{Printing, reading, and writing Messages} % \textbf{Printing, Reading, and Writing Messages} Protocol Buffer messages and descriptors implement \code{show} methods that provide basic information about the message: <<>>= p @ %For additional information, such as for debugging purposes, The \code{as.character} method provides a more complete ASCII representation of the contents of a message. <<>>= writeLines(as.character(p)) @ % \subsection{Serializing messages} A primary benefit of Protocol Buffers is an efficient binary wire-format representation. The \code{serialize} method is implemented for Protocol Buffer messages to serialize a message into a sequence of bytes (raw vector) that represents the message. The raw bytes can then be parsed back into the original message safely as long as the message type is known and its descriptor is available. <<>>= serialize(p, NULL) @ The same method can be used to serialize messages to files or arbitrary binary connections: <<>>= tf1 <- tempfile() serialize(p, tf1) readBin(tf1, raw(0), 500) @ %\subsection{Parsing messages} The \pkg{RProtoBuf} package defines the \code{read} and \code{readASCII} functions to read messages from files, raw vectors, or arbitrary connections. \code{read} expects to read the message payload from binary files or connections and \code{readASCII} parses the human-readable ASCII output that is created with \code{as.character}. The binary representation of the message does not contain information that can be used to dynamically infer the message type, so we have to provide this information to the \code{read} function in the form of a descriptor: <<>>= msg <- read(tutorial.Person, tf1) writeLines(as.character(msg)) @ The \code{input} argument of \code{read} can also be a binary readable \proglang{R} connection, such as a binary file connection, or a raw vector of serialized bytes. \section{Under the hood: S4 classes and methods} \label{sec:rprotobuf-classes} The \pkg{RProtoBuf} package uses the \proglang{S}4 system to store information about descriptors and messages. Each \proglang{R} object contains an external pointer to an object managed by the \pkg{protobuf} \proglang{C++} library, and the \proglang{R} objects make calls into more than 100 \proglang{C++} functions that provide the glue code between the \proglang{R} language classes and the underlying \proglang{C++} classes. \proglang{S}4 objects are immutable, and so the methods that modify field values of a message return a new copy of the object with \proglang{R}'s usual functional copy on modify semantics\footnote{\pkg{RProtoBuf} was designed and implemented before Reference Classes were introduced to offer a new class system with mutable objects. If \pkg{RProtoBuf} were implemented today Reference Classes would almost certainly be a better design choice than \proglang{S}4 classes.}. Using the \proglang{S}4 system allows the package to dispatch methods that are not generic in the \proglang{S}3 sense, such as \code{new} and \code{serialize}. The \pkg{Rcpp} package \citep{eddelbuettel2011rcpp,eddelbuettel2013seamless} is used to facilitate this integration of the \proglang{R} and \proglang{C++} code for these objects. Each method is wrapped individually which allows us to add user-friendly custom error handling, type coercion, and performance improvements at the cost of a more verbose implementation. The \pkg{RProtoBuf} package in many ways motivated the development of \pkg{Rcpp} Modules \citep{eddelbuettel2013exposing}, which provide a more concise way of wrapping \proglang{C++} functions and classes in a single entity. Since \pkg{RProtoBuf} users are most often switching between two or more different languages as part of a larger data analysis pipeline, both generic function and message passing OO style calling conventions are supported: \begin{itemize} \item The functional dispatch mechanism of the the form \verb|method(object, arguments)| (common to \proglang{R}). \item The message passing object-oriented notation of the form \verb|object$method(arguments)|. \end{itemize} Additionally, \pkg{RProtoBuf} supports tab completion for all classes. Completion possibilities include method names for all classes, plus \emph{dynamic dispatch} on names or types specific to a given object. This functionality is implemented with the \code{.DollarNames} S3 generic function defined in the \pkg{utils} package that is included with \proglang{R} \citep{r}. Table~\ref{class-summary-table} lists the six primary message and descriptor classes in \pkg{RProtoBuf}. The package documentation provides a complete description of the slots and methods for each class. % [bp] \begin{table}[t!] \centering \begin{tabular}{lccl} \hline Class & Slots & Methods & Dynamic dispatch\\ \hline `\code{Message}' & 2 & 20 & yes (field names)\\ `\code{Descriptor}' & 2 & 16 & yes (field names, enum types, nested types)\\ `\code{FieldDescriptor}' & 4 & 18 & no\\ `\code{EnumDescriptor}' & 4 & 11 & yes (enum constant names)\\ `\code{EnumValueDescriptor}' & 3 & \phantom{1}6 & no\\ `\code{FileDescriptor}' & 3 & \phantom{1}6 & yes (message/field definitions)\\ \hline \end{tabular} \caption{\label{class-summary-table}Overview of class, slot, method and dispatch relationships.} \end{table} \subsection{Messages} The `\code{Message}' \proglang{S}4 class represents Protocol Buffer messages and is the core abstraction of \pkg{RProtoBuf}. Each `\code{Message}' contains a pointer to a `\code{Descriptor}' which defines the schema of the data defined in the message, as well as a number of `\code{FieldDescriptor}'s for the individual fields of the message. <<>>= new(tutorial.Person) @ \subsection{Descriptors} Descriptors describe the type of a message. This includes what fields a message contains and what the types of those fields are. Message descriptors are represented in \proglang{R} by the `\code{Descriptor}' \proglang{S}4 class. The class contains the slots \code{pointer} and \code{type}. Similarly to messages, the \verb|$| operator can be used to retrieve descriptors that are contained in the descriptor, or invoke methods. When \pkg{RProtoBuf} is first loaded it calls \code{readProtoFiles} which reads in the example file \code{addressbook.proto} included with the package. The \code{tutorial.Person} descriptor and all other descriptors defined in the loaded \code{.proto} files are then available on the search path\footnote{This explains why the example in Table~\ref{tab:proto} lacked an explicit call to \code{readProtoFiles}.}. \subsubsection*{Field descriptors} \label{subsec-field-descriptor} <<>>= tutorial.Person$email tutorial.Person$email$is_required() tutorial.Person$email$type() tutorial.Person$email$as.character() class(tutorial.Person$email) @ \subsubsection*{Enum and EnumValue descriptors} \label{subsec-enum-descriptor} The \code{EnumDescriptor} type contains information about what values a type defines, while the \code{EnumValueDescriptor} describes an individual enum constant of a particular type. The \verb|$| operator can be used to retrieve the value of enum constants contained in the EnumDescriptor, or to invoke methods. <<>>= tutorial.Person$PhoneType tutorial.Person$PhoneType$WORK class(tutorial.Person$PhoneType) tutorial.Person$PhoneType$value(1) tutorial.Person$PhoneType$value(name="HOME") tutorial.Person$PhoneType$value(number=1) class(tutorial.Person$PhoneType$value(1)) @ \subsubsection*{File descriptors} \label{subsec-file-descriptor} The class `\code{FileDescriptor}' represents file descriptors in \proglang{R}. The \verb|$| operator can be used to retrieve named fields defined in the `\code{FileDescriptor}', or to invoke methods. % < < > > = % f <- tutorial.Person$fileDescriptor() % f % f$Person % @ \begin{Schunk} \begin{Sinput} R> f <- tutorial.Person$fileDescriptor() R> f \end{Sinput} \begin{Soutput} file descriptor for package tutorial \ (/usr/local/lib/R/site-library/RProtoBuf/proto/addressbook.proto) \end{Soutput} \begin{Sinput} R> f$Person \end{Sinput} \begin{Soutput} descriptor for type 'tutorial.Person' \end{Soutput} \end{Schunk} \section{Type coercion} \label{sec:types} One of the benefits of using an interface definition language (IDL) like Protocol Buffers is that it provides a highly portable basic type system. This permits different language and hardware implementations to map to the most appropriate type in different environments. Table~\ref{table-get-types} details the correspondence between the field type and the type of data that is retrieved by \verb|$| and \verb|[[| extractors. Three types in particular need further attention due to specific differences in the \proglang{R} language: booleans, unsigned integers, and 64-bit integers. \begin{table}[t!] \centering \begin{small} \begin{tabular}{lp{5cm}p{5.5cm}} \toprule Field type & \proglang{R} type (non repeated) & \proglang{R} type (repeated) \\ \cmidrule(r){2-3} double & \code{double} vector & \code{double} vector \\ float & \code{double} vector & \code{double} vector \\[3mm] uint32 & \code{double} vector & \code{double} vector \\ fixed32 & \code{double} vector & \code{double} vector \\[3mm] int32 & \code{integer} vector & \code{integer} vector \\ sint32 & \code{integer} vector & \code{integer} vector \\ sfixed32 & \code{integer} vector & \code{integer} vector \\[3mm] int64 & \code{integer} or \code{character} vector & \code{integer} or \code{character} vector \\ uint64 & \code{integer} or \code{character} vector & \code{integer} or \code{character} vector \\ sint64 & \code{integer} or \code{character} vector & \code{integer} or \code{character} vector \\ fixed64 & \code{integer} or \code{character} vector & \code{integer} or \code{character} vector \\ sfixed64 & \code{integer} or \code{character} vector & \code{integer} or \code{character} vector \\[3mm] bool & \code{logical} vector & \code{logical} vector \\[3mm] string & \code{character} vector & \code{character} vector \\ bytes & \code{character} vector & \code{character} vector \\[3mm] enum & \code{integer} vector & \code{integer} vector \\[3mm] message & \code{S4} object of class \code{Message} & \code{list} of \code{S4} objects of class \code{Message} \\ \bottomrule \end{tabular} \end{small} \caption{\label{table-get-types}Correspondence between field type and \proglang{R} type retrieved by the extractors. \proglang{R} lacks native 64-bit integers, so the \code{RProtoBuf.int64AsString} option is available to return large integers as characters to avoid losing precision; see Section~\ref{sec:int64} below. All but the \code{Message} type can be represented in vectors of one or more elements; for the latter a list is used.} \end{table} \subsection{Booleans} \proglang{R} booleans can accept three values: \code{TRUE}, \code{FALSE}, and \code{NA}. However, most other languages, including the Protocol Buffer schema, only accept \code{TRUE} or \code{FALSE}. This means that we simply can not store \proglang{R} logical vectors that include all three possible values as booleans. The library will refuse to store \code{NA}s in Protocol Buffer boolean fields, and users must instead choose another type (such as enum or integer) capable of storing three distinct values. <>= if (!exists("JSSPaper.Example1", "RProtoBuf:DescriptorPool")) { readProtoFiles(file="proto/int64.proto") } @ % We want a cleaner error message here. \begin{CodeChunk} \begin{CodeInput} R> a <- new(JSSPaper.Example1) R> a$optional_bool <- TRUE R> a$optional_bool <- FALSE R> a$optional_bool <- NA \end{CodeInput} \begin{CodeOutput} Error: NA boolean values can not be stored in bool Protocol Buffer fields \end{CodeOutput} \end{CodeChunk} \subsection{Unsigned integers} \proglang{R} lacks a native unsigned integer type. Values between $2^{31}$ and $2^{32} - 1$ read from unsigned integer Protocol Buffer fields must be stored as doubles in \proglang{R}. <<>>= as.integer(2^31-1) as.integer(2^31 - 1) + as.integer(1) 2^31 class(2^31) @ \subsection{64-bit integers} \label{sec:int64} \proglang{R} also does not support the native 64-bit integer type. Numeric vectors with integer values greater or equal to $2^{31}$ can only be stored as floating-point double precision variables. This conversion incurs a loss of precision, and \proglang{R} loses the ability to distinguish between some distinct integer variables: <<>>= 2^53 == (2^53 + 1) @ Most modern languages do have support for 64-bit integer values, which becomes problematic when \pkg{RProtoBuf} is used to exchange data with a system that requires this integer type. To work around this, \pkg{RProtoBuf} allows users to get and set 64-bit integer values by specifying them as character strings. On 64-bit platforms, character strings representing large decimal numbers will be coerced to \code{int64} during assignment to 64-bit Protocol Buffer types to work around the lack of native 64-bit types in \proglang{R} itself. The values are stored as distinct \code{int64} values in memory. But when accessed from \proglang{R} language code, they will be coerced into numeric (floating-point) values. If the full 64-bit precision is required, the \code{RProtoBuf.int64AsString} option can be set to \code{TRUE} to return \code{int64} values from messages as character strings. Such character values are useful because they can accurately be used as unique identifiers, and can easily be passed to \proglang{R} packages such as \pkg{int64} \citep{int64} or \pkg{bit64} \citep{bit64} which represent 64-bit integers in \proglang{R}. \section[Converting R data structures into Protocol Buffers]{Converting \proglang{R} data structures into Protocol Buffers} \label{sec:evaluation} The previous sections discussed functionality in the \pkg{RProtoBuf} package for creating, manipulating, parsing, and serializing Protocol Buffer messages of a defined schema. This is useful when there are pre-existing systems with defined schemas or significant software components written in other languages that need to be accessed from within \proglang{R}. The package also provides methods for converting arbitrary \proglang{R} data structures into Protocol Buffers and vice versa with a universal \proglang{R} object schema. The \code{serialize\_pb} and \code{unserialize\_pb} functions serialize arbitrary \proglang{R} objects into a universal Protocol Buffer message: <<>>= msg <- serialize_pb(iris, NULL) identical(iris, unserialize_pb(msg)) @ In order to accomplish this, \pkg{RProtoBuf} uses the same catch-all \code{proto} schema used by \pkg{RHIPE} for exchanging \proglang{R} data with Hadoop \citep{rhipe}. This schema, which we will refer to as \code{rexp.proto}, is printed in %appendix \ref{rexp.proto}. the appendix. The Protocol Buffer messages generated by \pkg{RProtoBuf} and \pkg{RHIPE} are naturally compatible between the two systems because they use the same schema. This shows the power of using a schema-based cross-platform format such as Protocol Buffers: interoperability is achieved without effort or close coordination. The \code{rexp.proto} schema natively supports all main \proglang{R} storage types holding \emph{data}. These include \code{NULL}, \code{list} and vectors of type \code{logical}, \code{character}, \code{double}, \code{integer}, and \code{complex}. In addition, every type can contain a named set of attributes, as is the case in \proglang{R}. The storage types \code{function}, \code{language}, and \code{environment} are specific to \proglang{R} and have no equivalent native type in Protocol Buffers. These three types are supported by first serializing with \code{base::serialize} in \proglang{R} and then stored in a raw bytes field. \subsection[Evaluation: Serializing R data sets]{Evaluation: Serializing \proglang{R} data sets} \label{sec:compression} <>= datasets <- as.data.frame(data(package="datasets")$results) datasets$name <- sub("\\s+.*$", "", datasets$Item) n <- nrow(datasets) @ This section evaluates the effectiveness of serializing arbitrary \proglang{R} data structures into Protocol Buffers. We use the \Sexpr{n} standard data sets included in the \pkg{datasets} package included with \proglang{R} as our evaluation data. These data sets include data frames, matrices, time series, tables, lists, and some more exotic data classes. For each data set, we compare how many bytes are used to store the data set using four different methods: \begin{itemize} \item normal \proglang{R} serialization \citep{serialization}, \item \proglang{R} serialization followed by gzip, \item normal Protocol Buffer serialization, and \item Protocol Buffer serialization followed by gzip. \end{itemize} <>= datasets$object.size <- unname(sapply(datasets$name, function(x) object.size(eval(as.name(x))))) datasets$R.serialize.size <- unname(sapply(datasets$name, function(x) length(serialize(eval(as.name(x)), NULL)))) datasets$R.serialize.size <- unname(sapply(datasets$name, function(x) length(serialize(eval(as.name(x)), NULL)))) datasets$R.serialize.size.gz <- unname(sapply(datasets$name, function(x) length(memCompress(serialize(eval(as.name(x)), NULL), "gzip")))) datasets$RProtoBuf.serialize.size <- unname(sapply(datasets$name, function(x) length(serialize_pb(eval(as.name(x)), NULL)))) datasets$RProtoBuf.serialize.size.gz <- unname(sapply(datasets$name, function(x) length(memCompress(serialize_pb(eval(as.name(x)), NULL), "gzip")))) clean.df <- data.frame(dataset=datasets$name, object.size=datasets$object.size, "serialized"=datasets$R.serialize.size, "gzipped serialized"=datasets$R.serialize.size.gz, "RProtoBuf"=datasets$RProtoBuf.serialize.size, "gzipped RProtoBuf"=datasets$RProtoBuf.serialize.size.gz, "ratio.serialized" = datasets$R.serialize.size / datasets$object.size, "ratio.rprotobuf" = datasets$RProtoBuf.serialize.size / datasets$object.size, "ratio.serialized.gz" = datasets$R.serialize.size.gz / datasets$object.size, "ratio.rprotobuf.gz" = datasets$RProtoBuf.serialize.size.gz / datasets$object.size, "savings.serialized" = 1-(datasets$R.serialize.size / datasets$object.size), "savings.rprotobuf" = 1-(datasets$RProtoBuf.serialize.size / datasets$object.size), "savings.serialized.gz" = 1-(datasets$R.serialize.size.gz / datasets$object.size), "savings.rprotobuf.gz" = 1-(datasets$RProtoBuf.serialize.size.gz / datasets$object.size), check.names=FALSE) all.df<-data.frame(dataset="TOTAL", object.size=sum(datasets$object.size), "serialized"=sum(datasets$R.serialize.size), "gzipped serialized"=sum(datasets$R.serialize.size.gz), "RProtoBuf"=sum(datasets$RProtoBuf.serialize.size), "gzipped RProtoBuf"=sum(datasets$RProtoBuf.serialize.size.gz), "ratio.serialized" = sum(datasets$R.serialize.size) / sum(datasets$object.size), "ratio.rprotobuf" = sum(datasets$RProtoBuf.serialize.size) / sum(datasets$object.size), "ratio.serialized.gz" = sum(datasets$R.serialize.size.gz) / sum(datasets$object.size), "ratio.rprotobuf.gz" = sum(datasets$RProtoBuf.serialize.size.gz) / sum(datasets$object.size), "savings.serialized" = 1-(sum(datasets$R.serialize.size) / sum(datasets$object.size)), "savings.rprotobuf" = 1-(sum(datasets$RProtoBuf.serialize.size) / sum(datasets$object.size)), "savings.serialized.gz" = 1-(sum(datasets$R.serialize.size.gz) / sum(datasets$object.size)), "savings.rprotobuf.gz" = 1-(sum(datasets$RProtoBuf.serialize.size.gz) / sum(datasets$object.size)), check.names=FALSE) clean.df<-rbind(clean.df, all.df) @ Figure~\ref{fig:compression} shows the space savings $\left(1 - \frac{\textrm{Compressed Size}}{\textrm{Uncompressed Size}}\right)$ for each of the data sets using each of these four methods. The associated table shows the exact data sizes for some outliers and the aggregate of all 104 data sets. Note that Protocol Buffer serialization results in slightly smaller byte streams compared to native \proglang{R} serialization in most cases (red dots), but this difference disappears if the results are compressed with gzip (blue triangles). % Sizes are comparable but Protocol Buffers provide simple getters and % setters in multiple languages instead of requiring other programs to % parse the \proglang{R} serialization % format. % \citep{serialization}. The \code{crimtab} dataset of anthropometry measurements of British prisoners \citep{garson1900metric} and the \code{airquality} dataset of air quality measurements in New York show the greatest difference in the space savings when using Protocol Buffers compared to \proglang{R} native serialization. The \code{crimtab} dataset is a 42 $\times$ 22 table of integers, most equal to 0, and the \code{airquality} dataset is a data frame of 154 observations of 1 numeric and 5 integer variables. In both data sets, the large number of small integer values can be very efficiently encoded by the \emph{Varint} integer encoding scheme used by Protocol Buffers which use a variable number of bytes for each value. The other extreme is represented by the \code{faithful} dataset of waiting time and eruptions of the Old Faithful geyser in Yellowstone National Park, Wyoming, USA \citep{azzalini1990look}. This dataset is a data frame with 272 observations of 2 numeric variables. The \proglang{R} native serialization of repeated numeric values is more space-efficient, resulting in a slightly smaller object size compared to the serialized Protocol Buffer equivalent. This evaluation shows that the \code{rexp.proto} universal \proglang{R} object schema included in \pkg{RProtoBuf} does not in general provide any significant saving in file size compared to the normal serialization mechanism in \proglang{R}. % redundant: which is seen as equally compact. The benefits of \pkg{RProtoBuf} accrue more naturally in applications where multiple programming languages are involved, or when a more concise application-specific schema has been defined. The example in the next section satisfies both of these conditions. \begin{figure}[t!] \begin{center} <>= old.mar<-par("mar") new.mar<-old.mar new.mar[3]<-0 new.mar[4]<-0 my.cex<-1.3 par("mar"=new.mar) plot(clean.df$savings.serialized, clean.df$savings.rprotobuf, pch=1, col="red", las=1, xlab="Serialization Space Savings", ylab="Protocol Buffer Space Savings", xlim=c(0,1),ylim=c(0,1),cex.lab=my.cex, cex.axis=my.cex) points(clean.df$savings.serialized.gz, clean.df$savings.rprotobuf.gz,pch=2, col="blue") # grey dotted diagonal abline(a=0,b=1, col="grey",lty=2,lwd=3) # find point furthest off the X axis. clean.df$savings.diff <- clean.df$savings.serialized - clean.df$savings.rprotobuf clean.df$savings.diff.gz <- clean.df$savings.serialized.gz - clean.df$savings.rprotobuf.gz # The one to label. tmp.df <- clean.df[which(clean.df$savings.diff == min(clean.df$savings.diff)),] # This minimum means most to the left of our line, so pos=2 is label to the left text(tmp.df$savings.serialized, tmp.df$savings.rprotobuf, labels=tmp.df$dataset, pos=2, cex=my.cex) # Some gziped version # text(tmp.df$savings.serialized.gz, tmp.df$savings.rprotobuf.gz, labels=tmp.df$dataset, pos=2, cex=my.cex) # Second one is also an outlier tmp.df <- clean.df[which(clean.df$savings.diff == sort(clean.df$savings.diff)[2]),] # This minimum means most to the left of our line, so pos=2 is label to the left text(tmp.df$savings.serialized, tmp.df$savings.rprotobuf, labels=tmp.df$dataset, pos=2, cex=my.cex) #text(tmp.df$savings.serialized.gz, tmp.df$savings.rprotobuf.gz, labels=tmp.df$dataset, pos=my.cex) tmp.df <- clean.df[which(clean.df$savings.diff == max(clean.df$savings.diff)),] # This minimum means most to the right of the diagonal, so pos=4 is label to the right # Only show the gziped one. #text(tmp.df$savings.serialized, tmp.df$savings.rprotobuf, labels=tmp.df$dataset, pos=4, cex=my.cex) text(tmp.df$savings.serialized.gz, tmp.df$savings.rprotobuf.gz, labels=tmp.df$dataset, pos=4, cex=my.cex) #outlier.dfs <- clean.df[c(which(clean.df$savings.diff == min(clean.df$savings.diff)), legend("topleft", c("Raw", "Gzip Compressed"), pch=1:2, col=c("red", "blue"), cex=my.cex) #interesting.df <- clean.df[unique(c(which(clean.df$savings.diff == min(clean.df$savings.diff)), # which(clean.df$savings.diff == max(clean.df$savings.diff)), # which(clean.df$savings.diff.gz == max(clean.df$savings.diff.gz)), # which(clean.df$dataset == "TOTAL"))),c("dataset", "object.size", "serialized", "gzipped serialized", "RProtoBuf", "gzipped RProtoBuf", "savings.serialized", "savings.serialized.gz", "savings.rprotobuf", "savings.rprotobuf.gz")] interesting.df <- clean.df[as.character(clean.df[,1]) %in% c("crimtab", "airquality", "faithful", "TOTAL"), c("dataset", "object.size", "serialized", "gzipped serialized", "RProtoBuf", "gzipped RProtoBuf", "savings.serialized", "savings.serialized.gz", "savings.rprotobuf", "savings.rprotobuf.gz")] interesting.df <- interesting.df[c(2,1,3,4),] # Print without .00 in xtable interesting.df$object.size <- as.integer(interesting.df$object.size) par("mar"=old.mar) @ \includegraphics[width=0.45\textwidth]{figures/fig-SER} % latex table generated in R 3.0.2 by xtable 1.7-0 package % Wed Nov 26 15:31:30 2014 % updated to R 3.3.1 on Sun Jul 10 17:29:41 CDT 2016 %\begin{table}[ht] %\begin{center} \begin{tabular}{rlrrrrr} \hline Data set & \code{object.size} & \multicolumn{2}{c}{\proglang{R} serialization} & \multicolumn{2}{c}{\pkg{RProtoBuf} serialization} \\ & & default & gzipped & default & gzipped \\ \hline \code{crimtab} & 7,936 & 4,641 (41.5\%) & 714 (91.0\%) & 1,655 (79.1\%) & 576 (92.7\%)\\ \code{airquality} & 5,496 & 4,551 (17.2\%) & 1,242 (77.4\%) & 2,874 (47.7\%) & 1,294 (76.4\%)\\ \code{faithful} & 5,136 & 4,543 (11.5\%) & 1,339 (73.9\%) & 4,936 \phantom{0}(3.9\%) & 1,776 (65.4\%)\\ \hline All & 609,024 & 463,833 (24\%) & 139,814 (77\%) & 436,746 (28\%) & 142,783 (77\%)\\ \hline \end{tabular} \end{center} \caption{(Top) Relative space savings of Protocol Buffers and native \proglang{R} serialization over the raw object sizes of each of the 104 data sets in the \pkg{datasets} package. Points to the left of the dashed $y=x$ line represent datasets that are more efficiently encoded with Protocol Buffers. (Bottom) Absolute space savings of three outlier datasets and the aggregate performance of all datasets. R version 3.3.1 was used for both the figure and the table. } \label{fig:compression} \end{figure} \section{Application: Distributed data collection with MapReduce} \label{sec:mapreduce} Protocol Buffers are used extensively at Google for almost all RPC protocols, and to store structured information on a variety of persistent storage systems \citep{dean2009designs}. Since the initial release in 2010, hundreds of Google's statisticians and software engineers use the \pkg{RProtoBuf} package on a daily basis to interact with these systems from within \proglang{R}. The current section illustrates the power of Protocol Buffers to collect and manage large structured data in one language before analyzing it in \proglang{R}. Our example uses MapReduce \citep{dean2008mapreduce}, which has emerged in the last decade as a popular design pattern to facilitate parallel processing of big data using distributed computing clusters. Big data sets in fields such as particle physics and information processing are often stored in binned (histogram) form in order to reduce storage requirements \citep{scott2009multivariate}. Because analysis over such large data sets may involve very rare phenomenon or deal with highly skewed data sets or inflexible raw data storage systems, unbiased sampling is often not feasible. In these situations, MapReduce and binning may be combined as a pre-processing step for a wide range of statistical and scientific analyses \citep{blocker2013}. There are two common patterns for generating histograms of large data sets in a single pass with MapReduce. In the first method, each mapper task generates a histogram over a subset of the data that it has been assigned, serializes this histogram and sends it to one or more reducer tasks which merge the intermediate histograms from the mappers. In the second method, illustrated in Figure~\ref{fig:mr-histogram-pattern1}, each mapper rounds a data point to a bucket width and outputs that bucket as a key and '1' as a value. Reducers count how many times each key occurs and outputs a histogram to a data store. \begin{figure}[t!] \begin{center} \includegraphics[width=0.9\textwidth]{figures/histogram-mapreduce-diag1.pdf} \end{center} \caption{Diagram of MapReduce histogram generation pattern.} \label{fig:mr-histogram-pattern1} \end{figure} In both methods, the mapper tasks must choose identical bucket boundaries in advance if we are to construct the histogram in a single pass, even though they are analyzing disjoint parts of the input set that may cover different ranges. All distributed tasks involved in the pre-processing as well as any downstream data analysis tasks must share a schema of the histogram representation to coordinate effectively. The \pkg{HistogramTools} package \citep{histogramtools} enhances \pkg{RProtoBuf} by providing a concise schema for \proglang{R} histogram objects: \begin{example} package HistogramTools; message HistogramState { repeated double breaks = 1; repeated int32 counts = 2; optional string name = 3; } \end{example} This \code{HistogramState} message type is designed to be helpful if some of the Map or Reduce tasks are written in \proglang{R}, or if those components are written in other languages and only the resulting output histograms need to be manipulated in \proglang{R}. \subsection[A simple single-machine example for Python to R serialization]{A simple single-machine example for \proglang{Python} to \proglang{R} serialization} To create \code{HistogramState} messages in \proglang{Python} for later consumption by \proglang{R}, we first compile the \code{histogram.proto} descriptor into a python module using the \code{protoc} compiler: \begin{verbatim} protoc histogram.proto --python_out=. \end{verbatim} This generates a Python module called \code{histogram\_pb2.py}, containing both the descriptor information as well as methods to read and manipulate the histogram message data. The following simple Python script uses this generated module to create a histogram (to which breakpoints and binned data are added), and writes out the Protocol Buffer representation to a file: \begin{Code} from histogram_pb2 import HistogramState; hist = HistogramState() hist.counts.extend([2, 6, 2, 4, 6]) hist.breaks.extend(range(6)) hist.name="Example Histogram Created in Python" outfile = open("/tmp/hist.pb", "wb") outfile.write(hist.SerializeToString()) outfile.close() \end{Code} The Protocol Buffer created from this \proglang{Python} script can then be read into \proglang{R} and converted to a native \proglang{R} histogram object for plotting. The code below first attaches the \pkg{HistogramTools} package which imports \pkg{RProtoBuf}. Then reads all of the \code{.proto} descriptor definitions provided by \pkg{HistogramTools} and adds them to the environment as described in Section~\ref{sec:rprotobuf-basic}. Next the serialized Protocol Buffer is parsed using the \code{HistogramTools.HistogramState} schema. Finally the Protocol Buffer representation of the histogram is converted to a native \proglang{R} histogram object with \code{as.histogram} and passes the result to \code{plot} (see Figure~\ref{figure}). \lstdefinelanguage{jss} {sensitive=false, morecomment=[l]{R>}} \lstset{language=jss, basicstyle=\ttfamily, numbers=left, numberstyle=\tiny, stepnumber=2, numbersep=5pt, columns=fullflexible, keepspaces=true, showstringspaces=false, commentstyle=\textsl} %\begin{Code} \begin{lstlisting} R> library("HistogramTools") R> readProtoFiles(package="HistogramTools") R> hist <- HistogramTools.HistogramState$read("/tmp/hist.pb") R> hist [1] "message of type 'HistogramTools.HistogramState' with 3 fields set" R> plot(as.histogram(hist), main="") \end{lstlisting} %\end{Code} %% DEdd 2016-07-10 Taking a shortcut here an showing a prepared %% HistogramTools chart to not depend on HistogramTools %% on Travis CI etc \begin{center} <>= require(HistogramTools) readProtoFiles(package="HistogramTools") hist <- HistogramTools.HistogramState$read("proto/hist.pb") plot(as.histogram(hist), main="") @ \includegraphics[width=0.45\textwidth]{figures/HistogramTools} \end{center} This simple example uses a constant histogram generated in \proglang{Python} to illustrate the serialization concepts without requiring the reader to be familiar with the interface of any particular MapReduce implementation. In practice, using Protocol Buffers to pass histograms between another programming language and \proglang{R} would provide a much greater benefit in a distributed context. For example, a first-class data type to represent histograms would prevent individual histograms from being split up and would allow the use of combiners on Map workers to process large data sets more efficiently than simply passing around lists of counts and buckets. One of the authors has used this design pattern with \proglang{C++} MapReduces over very large data sets to write out histogram protocol buffers for several large-scale studies of distributed storage systems \citep{sciencecloud,janus}. \section{Application: Data interchange in web services} \label{sec:opencpu} The previous section described an application where data from a program written in another language was saved to persistent storage and then read into \proglang{R} for further analysis. This section describes another common use case where Protocol Buffers are used as the interchange format for client-server communication. Network protocols such as HTTP provide mechanisms for client-server communication, i.e., how to initiate requests, authenticate, send messages, etc. However, network protocols generally do not regulate the \emph{content} of messages: they allow transfer of any media type, such as web pages, static files or multimedia content. When designing systems where various components require exchange of specific data structures, we need something on top of the network protocol that prescribes how these structures are to be represented in messages (buffers) on the network. Protocol Buffers solve this problem by providing a cross-platform method for serializing arbitrary structures into well defined messages, which can then be exchanged using any protocol. \subsection[Interacting with R through HTTPS and Protocol Buffers]{Interacting with \proglang{R} through HTTPS and Protocol Buffers} One example of a system that supports Protocol Buffers to interact with \proglang{R} is OpenCPU \citep{opencpu}. OpenCPU is a framework for embedded statistical computation and reproducible research based on \proglang{R} and \LaTeX. It exposes a HTTP(S) API to access and manipulate \proglang{R} objects and execute remote \proglang{R} function calls. Clients do not need to understand or generate any \proglang{R} code: HTTP requests are automatically mapped to function calls, and arguments/return values can be posted/retrieved using several data interchange formats, such as Protocol Buffers. OpenCPU uses the \code{rexp.proto} descriptor and the \code{serialize\_pb} and \code{unserialize\_pb} functions described in Section~\ref{sec:evaluation} to convert between \proglang{R} objects and Protocol Buffer messages. \subsection[HTTP GET: Retrieving an R object]{HTTP GET: Retrieving an \proglang{R} object} The \code{HTTP GET} method is used to read a resource from OpenCPU. For example, to access the data set \code{Animals} from the package \code{MASS}, a client performs the following HTTP request: \begin{verbatim} GET https://demo.ocpu.io/MASS/data/Animals/pb \end{verbatim} The postfix \code{/pb} in the URL tells the server to send this object in the form of a Protocol Buffer message. % Alternative formats include \code{/json}, \code{/csv}, \code{/rds} and others. If the request is successful, OpenCPU returns the serialized object with HTTP status code 200 and HTTP response header \code{Content-Type: application/x-protobuf}. The latter is the conventional MIME type that formally notifies the client to interpret the response as a Protocol Buffer. Because both HTTP and Protocol Buffers have libraries available for many languages, clients can be implemented in just a few lines of code. Below is example code for both \proglang{R} and Python that retrieves an \proglang{R} data set encoded as a Protocol Buffer message from OpenCPU. In \proglang{R}, we use the HTTP client from the \code{httr} package \citep{httr}. In this example we download a data set which is part of the base \proglang{R} distribution, so we can verify that the object was transferred without loss of information. <>= library("RProtoBuf") library("httr") req <- GET('https://demo.ocpu.io/MASS/data/Animals/pb') output <- unserialize_pb(req$content) identical(output, MASS::Animals) @ Similarly, to retrieve the same data set in a \proglang{Python} client, we first compile the \code{rexp.proto} descriptor into a python module using the \code{protoc} compiler: \begin{verbatim} protoc rexp.proto --python_out=. \end{verbatim} This generates \proglang{Python} module called \code{rexp\_pb2.py}, containing both the descriptor information as well as methods to read and manipulate the \proglang{R} object message. We use the HTTP client from the \code{urllib2} module in our example to retrieve the encoded Protocol Buffer from the remote server then parse and print it from \proglang{Python}. \begin{verbatim} import urllib2 from rexp_pb2 import REXP req = urllib2.Request('https://demo.ocpu.io/MASS/data/Animals/pb') res = urllib2.urlopen(req) msg = REXP() msg.ParseFromString(res.read()) print(msg) \end{verbatim} The \code{msg} object contains all data from the \code{Animals} data set. From here we can easily extract the desired fields for further use in \proglang{Python}. \subsection[HTTP POST: Calling an R function]{HTTP POST: Calling an \proglang{R} function} The previous example used a simple \code{HTTP GET} method to retrieve an \proglang{R} object from a remote service (\pkg{OpenCPU}) encoded as a Protocol Buffer. In many cases simple \code{HTTP GET} methods are insufficient, and a more complete RPC system may need to create compact Protocol Buffers for each request to send to the remote server in addition to parsing the response Protocol Buffers. The \pkg{OpenCPU} framework allows us to do arbitrary \proglang{R} function calls from within any programming language by encoding the arguments in the request Protocol Buffer. The following example \proglang{R} client code performs the remote function call \code{stats::rnorm(n = 42, mean = 100)}. The function arguments (in this case \code{n} and \code{mean}) as well as the return value (a vector with 42 random numbers) are transferred using Protocol Buffer messages. RPC in \pkg{OpenCPU} works like the \code{do.call} function in \proglang{R}, hence all arguments are contained within a list. <>= library("httr") library("RProtoBuf") args <- list(n=42, mean=100) payload <- serialize_pb(args, NULL) req <- POST ( url = "https://demo.ocpu.io/stats/R/rnorm/pb", body = payload, add_headers ( "Content-Type" = "application/x-protobuf" ) ) output <- unserialize_pb(req$content) print(output) @ The \pkg{OpenCPU} server basically performs the following steps to process the above RPC request: <>= fnargs <- unserialize_pb(inputmsg) val <- do.call(stats::rnorm, fnargs) outputmsg <- serialize_pb(val) @ \section{Summary} \label{sec:summary} Over the past decade, many formats for interoperable data exchange have become available, each with its unique features, strengths and weaknesses. Text based formats such as CSV and JSON are easy to use, and will likely remain popular among statisticians for many years to come. However, in the context of increasingly complex analysis stacks and applications involving distributed computing as well as mixed language analysis pipelines, choosing a more sophisticated data interchange format may reap considerable benefits. %Protocol Buffers is itself not a protocol. %Forward-compatibility is one of the features. No need to re-iterate those The Protocol Buffers standard and library offer a unique combination of features, performance, and maturity, that seems particularly well suited for data-driven applications and numerical computing. The \pkg{RProtoBuf} package builds on the Protocol Buffers \proglang{C++} library, and extends the \proglang{R} system with the ability to create, read, write, parse, and manipulate Protocol Buffer messages. \pkg{RProtoBuf} has been used extensively inside Google for the past five years by statisticians, analysts, and software engineers. At the time of this writing there are over 300 active users of \pkg{RProtoBuf} using it to read data from and otherwise interact with distributed systems written in \proglang{C++}, \proglang{Java}, \proglang{Python}, and other languages. We hope that making Protocol Buffers available to the \proglang{R} community will contribute to better software integration and allow for building even more advanced applications and analysis pipelines with \proglang{R}. \section*{Acknowledgments} The first versions of \pkg{RProtoBuf} were written during 2009--2010. Very significant contributions, both in code and design, were made by Romain Fran\c{c}ois whose continued influence on design and code is greatly appreciated. Several features of the package reflect the design of the \pkg{rJava} package by Simon Urbanek \citep{rjava}. The user-defined table mechanism, implemented by Duncan Temple Lang for the purpose of the \pkg{RObjectTables} package, allows for the dynamic symbol lookup. Kenton Varda was generous with his time in reviewing code and explaining obscure Protocol Buffer semantics. Karl Millar and Tim Hesterberg were very helpful in reviewing code and offering suggestions. Saptarshi Guha's work on \pkg{RHIPE} and implementation of a universal message type for \proglang{R} language objects allowed us to add the \code{serialize_pb} and \code{unserialize_pb} methods for turning arbitrary \proglang{R} objects into Protocol Buffers without a specialized pre-defined schema. Feedback from two anonymous referees greatly improved both the presentation of this paper and the package contents. \bibliography{RProtoBuf-paper} \begin{appendix} \section[The rexp.proto schema descriptor]{The \code{rexp.proto} schema descriptor} \label{rexp.proto} Below a print of the \code{rexp.proto} schema (originally designed by \citealt{rhipe}) that is included with the \pkg{RProtoBuf} package and used by \code{serialize\_pb} and \code{unserialize\_pb}. \begin{verbatim} package rexp; message REXP { enum RClass { STRING = 0; RAW = 1; REAL = 2; COMPLEX = 3; INTEGER = 4; LIST = 5; LOGICAL = 6; NULLTYPE = 7; LANGUAGE = 8; ENVIRONMENT = 9; FUNCTION = 10; } enum RBOOLEAN { F=0; T=1; NA=2; } required RClass rclass = 1; repeated double realValue = 2 [packed=true]; repeated sint32 intValue = 3 [packed=true]; repeated RBOOLEAN booleanValue = 4; repeated STRING stringValue = 5; optional bytes rawValue = 6; repeated CMPLX complexValue = 7; repeated REXP rexpValue = 8; repeated string attrName = 11; repeated REXP attrValue = 12; optional bytes languageValue = 13; optional bytes environmentValue = 14; optional bytes functionValue = 15; } message STRING { optional string strval = 1; optional bool isNA = 2 [default=false]; } message CMPLX { optional double real = 1 [default=0]; required double imag = 2; } \end{verbatim} \end{appendix} \end{document} RProtoBuf/inst/doc/RProtoBuf-intro.pdf0000644000176200001440000122345513164671405017407 0ustar liggesusers%PDF-1.5 % 5 0 obj << /Type /ObjStm /N 100 /First 812 /Length 1043 /Filter /FlateDecode >> stream xڥWMo8Wc ,~\f!@ +ѱ[2Ly_l+q"wcf"(p3eI dIE>5IiI:VHzGJReޤj,iW` +IZ&33AcF$kqÐ rf,9'jp Eࢩ,U^`5yqqn,p APH TW$$I\QD- y$X P. ,VVigq)v#0DWR<\q'"6K䆾b<߂G3 \{?IDF2BtZ D~ZX*5I l$W1{[OW&zh|K>|C_K&%@bnk;=Rzadf7CӚYh.SfU[rQM{HsO/|/x7|idSu˸A=Ҧ~!\F-c)FiX͡/9m~zns'1iشt1l.'" c1*.eߥ;ahMSS&L4%z3)`Se„nH$RLeyС@Mi%?RiڪdllJUԡIc~W/&C*b6szm.5mCIӫi6)כv=%3e\DOmG)a|E9VNXķE.0> M> stream xڥVrF+h_$>\JN9ɹk6D0r>=$eޙHQӃCb5 (DoP3$P4%4Pi &-Ij@2h"I rl)' :#&$Cs\Hdo` Q)8W"f(E)"BP6)(݃`@/n D@p <4U /1k8tc=P Zg(#֩al@=vW^{mi!jߠ@()`PyP* /@(`VuILa!jDXR'`(u hxRG4QDoT!khxޛƏ`L)ws?oś_<,2Oݶvec:|\eN7ݪݶݜ)ϫqy ~ǚp)3=OSk)~>US~~WO ݸ~ >6UلP?)@>Xб{z2RVfl=%Paơ}CU0o7 E~Fso+Qkqm]E=Wf?aoc0U8Oz؅Q3z h; -gл>yU/OˑwХr]*'CʡW7ts]*5Cʉ7㼪 .g:*uq2R9Oǰ;mC\]pPossxa>.ۧ,|Cfr\'W~+ƮNJ6m|̖+=#đ?~>Oҍy۩,N?= lg" endstream endobj 509 0 obj << /Length 2114 /Filter /FlateDecode >> stream x[oHWX32}2Rk$ڗ>`\vLFt3B)ps >-†`RK*swo>QP Q:8 ')bW*8_ӓ<+whXh̵ ߦ12I)J(-/jT:*%-,a=^#%|Suq>(Wř!$9Q}l,O#.#D#UGąD RH~;Cn l2 W/u=Hc?B%=܆E6+oƥ6.}dW,\X߭GVEup:A,mZ$8OMKѢ梻(2? գWu?,[Uǵ$˺0NHLeܿdjZ͜q1ȈMlLeUe4*#JB".0qb7VꝆ&kYJ**Q  }H2+o ]|_~q'q{vܖ,.צǯem׻MS$n[oPwAW "jnm I6漌b' 88Ob8վTo t ZNV_٢h^ו|Uq|T9{U8BH^U8"BPIU>M˭ Et]J-uMFcC/ ݭn4\ɳ'fzWPKSGT.*\C$Ri}PՎpګ2S}!lFe Wėm9G]>Jӡ0md(?Ly Ea4?mܬd'ؖ{g*7?֡Uǡ ϣ?="Ư0~ C %~촵jCӞ1J-&y?09f1΃1`^d2jQh[ʭG֚<ڬviZ#Ibj`#sn,qG6+݆ԈMvlj@PZw5n.H.(O]kw#xG!, endstream endobj 580 0 obj << /Length 1230 /Filter /FlateDecode >> stream xoHWHٟ^IR5tIBـ[csR~vBl'!333e5mCd2\+-^fp]F%z9rk8>đpTDH3,RU\'Li2}S%vz}4<;-}J"m*Ggc <($Lr!GVi :AXaƓ978_#LlIj<(H6єǶq9N݈Mp82 ~guZeZa7A48_DvkUE5*4!$zd BH)ꨋ,rf߅-xSȊaLx? U^Xh>zg[ƜHɩg~S?3N j.jl9zʭ{X;q)^@]e,'] $J̠~A(AkR\څ.%'a6R?0+1DXث/ك9["/d.;Pinh=F=LK`>?(ݵq@rԸ:Td|y 5bIz[K\Z5 C|+^Mwgfa lo2yG aKaW1Ol4V"ң~0n\+H:[%y4E8iъ*ٲt8abȶl%zU 08}#w * 0$M!MK-bA%B?t! HG vGZN{;-9QeA NAغk0 ൠL y @xf-l2B%C'zj,1+ե2z..}M=:;j&(BD7~mEMDȪ%鈔Л#pv YOA9,Sy97 :^NCYc = /WnjվjmpVAa5@f = wdPcegks?v {T7!/2gW08 .mmb=>ZJu0̡,O#sX_ͤFbTLW'?~$SbOgAc'iUI A<&q菏N-V_[~woc=_(U[}c^]Kl[o*Y!p; endstream endobj 407 0 obj << /Type /ObjStm /N 100 /First 879 /Length 2717 /Filter /FlateDecode >> stream xڵ[n7}6oK K 5,/ƣAL{#AZmg1,˂kb eur35^OjxnͼvkXѳ?/zwKayi{1f}u;-?H׸t}ݤn3^q=ÃA?[~{=O{u5Mn&ỷYmwx9p90܎x7ԾW/­دֻzɾ~ׇLr}7lPz|ί׿^jxWó «ذ{WaoCNjIa;_bwa'7~lK%iI,mYd$xI%K/ ^,xYe˂/ ^,xY+W^"xE Zi^ mv9_}uVi1뚙O3\*ofNzLEGv-Dspvvv0>cǯ-V^Io?}\owzvizjXm9j aUOX L֋5K{x7볎9uyYvO6-iÞ\?Î!5Gae8rIr>-`#Q>pJfiɅ92q"?lPPAAq*? ApkSй& Ԏ3L(jN"Qa?8؟H:"pvhNTR*ib[xNdq* Y 85YsIMOr$MmM 6Ngd]z67dw[а4 $hcA11?$|?hA;KIlb6pH]c$Hu'I󱁳FS &4o{g<̡Gm)X!BF2kqhOl{&$pm%8;nBs k5?uv z<ۡ IVch]v)COi)˖wmJvHL| D5Fڹ <`5@AG* IJopdb핞3FH`g[K䌘zLjADrY)-mA~n [Np?-\aHɃZl7v,A l4H%P>O wpS ˕`=F:i 1>ȷa>F:})̈S E`gwHB6BUwf|226o.l zX] [^8JGH}__p|X_yUK{Oo;kGHa+3KDt¡_bqWaU{ڥ/X}lgBr=~ټGV鴛+Sg.N U Ʃ5(]twDJ_-/0Bjx=~[mr)}QL_[oj5IIIIKfi祊 > stream x[ے6}WmC-oqV\*ުHT≶4 \9 Jnz۰n;gQB|ӊZzP\w@|ީfϻ,1t.cBjŨo[e(D{gtp [ U P}~4ۛc@CqZAօb#{m[Qc< | =:@tû^bx|~)x1#]ekvx2ɸ2FaHh!=[FC]bz@z@73 pI8S~Vb@ɬڝXnn67/)@_9Eq,ѱ JHa ~ "CU m=߆qnoJ:q,(G#1?~XRI&$8_^_U#h[Btgׯ5n?xYebQo\^p|S4!NIJs7_3$fJ[f8uMb0P?giskG J̢QȑIb$AHo]j8 R!8NN% ipߴw#ޑjA )_ذ|Ӭ IW] U"I Qϫow ]Fϰ v9 w2ΝRXy2yUbuUGm:[( {)a{].Sȕ}ʺѲ"gcI&& %IXErqksB:g]W#w[ uQYꍽ|մd¦0c OkG #yr7WQ㴚!CfG9?GF4"LUT?_(Ge{qQ ' rDf1)Ό*]6pO~j@L:+F$ E_ jM}|k?bgXyX] E0xAYDbW~ϞjаdC)bjte^j^(K (n*EN{ᔖavho03>b._JΝRp1*7:f:S.h0oԵd,ҼN}c4KqBΤދΧOeJxF:}=Lg1!y$aӮrr8kW\Ƚs;Ì9Bzv wlcUW ]g7:|Z 7y5Ϊjczτ~vl܏j>ub= VQHΩ>[l%W8^ # lBDÓ #8u'SSv3W5hR](9/0:]((9s:ɯ(\(Db*S+_hkNR4PTT=b`Y[reW EоU@X-m_lyAVfHLo.85=2qd],ŹWs! N&=Q=;A菪E]e4EBhw0nK=XmYJMd /<ZͯE6i ǾtjҐJe>z Ă+:d~+~(P,SxePxtqnĩ?Љ&jG endstream endobj 617 0 obj << /Length 2974 /Filter /FlateDecode >> stream x[[H~_a΃#vfW,4 xp'NLK0):Tչ|uޥ'$/'$bLyK͖'x@3'1 ﳧϫֿJLrމ +9ҪjNQpeXx!IFZ>Vr[F*v_@ b3;*$\%%isz6  f[ﳥ3E"´ZOZ-gNEBM ɍ>9?y,=;_x&Z?Ͻw~T\}v২bc8,*q -0xz޸QU37S;9zv^yI2wL % 8Or֡d!PЋp,I&[ᒇ w`<\_%Glv?)$ظ_ח, $h`o)lV%y6 *-w=IVct̸tCUUqu_?-&Bb#O\4u8ŋqhpК;fmJXk19B̹ !\ O`(?cSGkyUF뵾rUn5^6u|{a P>9b8 @S7Ӛrp e[qtsZf0 P :-grV|y]VaD AԭuSҧ =Ph&lh vtSL\ဵ8tJ>Z{岓E\y /80”z[G0D?Gg˷ɻ{7py\H2Η Q~+:,KH' t91[r $y*h[;|̌yEřmsF&S;U2*K7ci>vaeǬ_rV=ʳy41nCӳmG͐#t=C|ջƵ88*yFxuP{F9S@t3I:n!@TҚB,(qRFg3 MR&z㬳*v믩ޖf5<.gE}4HknfeaT¼>;Fy)=`lNZ곔8y3Id?rG%l0hϮ,)siSuIQ qg<˼&L_k,2RgH&}тp"ŮBtS”Z%봔nOEA]Ƣx!F.i 7`$# Kf[{Cc wb9z 0 :o`\&Aֻ|pT_/_v:*ڮo/O=y:,^K%Nm^u\V۹ A*Tk=c{$?ng|w}eĔfSVDdPSŔ^%?uNc}3ctc-! T`lPDO '0=Ie[`'oN^5=4PuD2HZ2?ЛF!gy.3|O[C  d쭿* |NI2fU-Fe'S1W+}gʤⲮ9h<)g҂^*5(P S}S#;zLQnda[Ev5 ;/fQP@=~bjJ:Qh}M*!bӞqXK{#;%a&aM ea@niYFZvhBT F#g38*sv|n6ܑРM?jl9<b֔ [ 8a5zWE\#vZ ttSb(MwyF2tFRZ>nJvrWhlnKoǸ~+9!Rvy&!Gn[PmV?4[̎]b I~5VTp;3I?nqzߤҊT endstream endobj 622 0 obj << /Length 2852 /Filter /FlateDecode >> stream x[_۸O!N S K{I8ͶɃVwؖ#٦PdIX\6IIpDfHc J# (SD /{Wɐ.f( 8T-ayQbUzO^T IpZ<0 $jE6t)EwÀpumמVHZAt(th` q|z:Kj`%G+o(k^BIw\+E л^x7z%\Pf>{{Grad$K)6wSx̢M&y0.32{bqbp3Z[+I+yc3Z` Sid;?fr6*ܖvzaԖWX%y6ʊ$ZهuT>%nȭΖi6ڍ]m [uتIWgqeË Q3`P]auD‹.77GKMFH"ڝRcT0?6regu RPk^jZ纰7pZ)]vZyt/-1mVPj:UC"r7mશOlt3qLҶ9Yz1h~xN8xG GRRbBh'f3>愠6ZGb\g>b({.#pI!tOg2JVc~20#C=tU(]u0DŽ8@ Tt0p/W- {GM_x f4l9x4/򝶄Ĥ)QAflN q(e{ӂ[a',;B7"-09K4N>-:+M-̌,Mmh)EA/>ne5Hai*wyd '2@- 43Em4{e"@\cػv50ufy%Nx~"I7o(z3%Y+,K{@^q1%tװgNw5Nrd!'0VT&L[F~lU0@KV)Cb'v( >W,~='L_̠܋"d`! 0?Xu퓋 {[47zkE9LB}0TBvǵ.Ӆ_GmCR&3(Ob'~Y{+*-n]щ &éXRM䑥/5<KzLI4QJj4ɴ0=*cm4Xc Vq*X\C>d4\+-cm[; bM̔wgπwlAYbؼt\l9-v= QoKDs/fRT~X$9Z7r h ޵m:/B;x29`\:c $DЖ-Q|eQ\5(Gob'tdui[S mc` YmsTؔI_G-N@a1/n|QQ#'eԢ\d >{L`mSwGE7:j[ Ͱ)[u#ʪqeHo1C~BB: ,3H {R< TIS30&gL)Dl0sVlv✣{QuNfAժ< x6*]٘6!}uaBrn6Kq '*c13.%9 $sZ7/\4`Y(0erS%2m3OUjVSJ4Gq7@r\4Y{Gp?J_,`i&g[&UCbqrK~>xۏQߜq\sntLnHLGXu:09:2jMmW7Mygp%SCfuV4xɦWR#ԠE.J=WmϷZw"Q}ޟa<! |zqbJ"QNUpep3X x{{eSI ޘP.oGr;ڷgofܽK|f>W) Qo)c|eBtrJЕ._JҖvڻvuu(G'n\=;W?oՙx@..>h7`W9m`G($s:AmMr3r]^m\ n=ۍ 2_USGD 儹P;gɶYfz@{nY~`xN ?'H@3#**|2$+zLV'l3ނoE537h L~RbBO= <9iG&eȆU>-ۧWO͖KuL PƲyᤑO@BD>=ԁǶ<7 rPrs?ql: jIOװWH*^'F8rϓQڞH\Ăz&:S~e. T^j`D͓ aЫ[sxBk4bƅoHhOd.wAj7rU#~[M6fxp> stream x[o6_!1oQ+pX)p(zi{Ŗ]m')7,ʲj$5 7C_`sf}`8/0b@}fD ~;FTrB`C@xy . pzK^QXz0";,1fz?4mi5Z2>C3xJ q ۟gKxKNBG($'_E~Xjc~||s5%"TP1kԶ=˹kk#&ض\6~'YG::qrp"N.aV>xF|qs.4.߆Jە|uiHٟ,hbִ` ."$EB4$w$0Tm!jҬ<˳,Uio̸j3㳆H3@:^D>Azq&H?`p4폡r@ =]Kݨ) RrDjv_H4(@OknD=IY^7aYdY_]9A7]>B_bB4T Bظ߈=Xkgq3|A~i{X/^_ky)yZIƫ?GV8D8VxsmGkyMNiUE\>yVNd*v"rt,q"p@/z8()%c[?tMdmq\hvH٣#`J.}O  a<꧞ O4<]Cϙa˨.#B@\,ˁAgր t 1NYd=Oۉ 砝ԳJt+Hw?ZA+BD~j{jT7<)gE3ݎjz׏?Cvl6n݉ ؍{azp]\ 'j $VSYIdUmCWfE8YZيRC yn |똃IIE^[6Tq;҃^WFBfP:B"zucxH4Y I4h|bJp}rns:Ojyi(i 8v8FwkFj@K2+.l9톰}:>5㰓[>b%cvC؈F/rE >jD2W]Ry,7V.O M'.1.YAzIQ(E[[N=rI˂#6e6=t"E~j_l8BE"L:u~YXtE`Ѱ2eԬE ghq )yc]6pM?q6]WvF' uUX8E$hQ\Q ) ;+1U&E:BQNb<]}r! P#V[xVE+p-][B4{t"ʽl +$7mNjB !yQKAz1Λ@頒pO Dsz9>zAl3khE׬5k"AȹW;ImTSVۈ[Ⱥ M\w޻t&nXvad"Kܦalu6[:n DKbt@Ǫڔonnf~$P1*V˛M> stream x[ے}߯@Yz, \I#[rb]6Ƀ"& %+O\ $:V9U=}N( n("O F $%JA2 ,7}k^DJ,?/bE͝WH,9Mup!#NxO)ևɚ?r @DH$pM_D$^TӅw8BDD|k@7ys"RE02kW4P)a ڕǿ&Ө\buPꗼt." qδ>|F R,[+a5_7\2y*miϗmUmq]e+5M䳟~41P(SJRiE:4%t#+fJ^ 'r\K\PM]x@ZTIQ$NMk9%\n|CcSIǶFz2e +q~m:$Oz]dMveFNg WΌjy^dk"jO`av` xs /0`Xm(dLqe@UX`ZopS{9K0[7y[kاyl|7y{[j fY[;tſΣWJb.` X =SQzRfTE()>/3Äs$]`eD8I|]Wقb}RL=Z??5mr*y7KEQfGXQ,_FA U>j9z?ZJͭF/!k+CX㏌jX@Ldfܷ[d:;fa0Jeh'1}J;Gy:ZiH&:VZF6X2X( ]gM7΅JQf _TT,5x5_N6f:w)\k0Y->j9')ߢM2?EäOPc],jGtB1Yˇt)V)d$s5O#t)c3Yz&};P9tI *'T/z34m}b&o{ L`:JM* (WX"f]ݦHl3oL؏+J<@4M]k.drftdU wzbm\R@ 2[AhGQbDJ>:N݁:(@9+p<f`n)5 8Q/G}<qgVn{pDW"I ,o  Ҟ^b1˻zh q=PΛ ?$Ĩp6l<DqD8OC|)3*CczB?Ŕ^\3X#? q߹02дqoJ945կGf5.s<' `2Z`X5绢`q 0#$$ٌEFb-2vJZK|-k﮵8󶆙%a R}}>?#a[mrY!yPumdd& Jsey/o6ZĥimY?zެsn ]<tb+G b0x&IÛ9٭1&"E,P̭nO|Í쭝 3߰q+ffۏJ0&>%4@M:e۬1#xCHF9&]2;otc` g B{ĕ0?SmUaP0B}M0Y}f <I="DO &{, ӯ׸mD4NX\ ,ÓT; Ǣ#'-geZ50 5*f!#qwpo^=mފ_t6kBrI̹?7Q>uo,Qxc' D(>+1U4jdY ;M}ɐ[9>ޠbBjދ W2o{A'Ma +QULZysl~+v9ۈeUjg4JM>cwKkm/u~ZTfHau{!n_O|BTg!R.sQ!~5#5 FW:vq s-4*Jg{pL$ ki;4PkxL]:诏u* qe@X-e&w 86xdEҡ=>cmoٱC4gRT%JMOJuUO;fE::.>`ꌱh ~)zԝ'$j]_[E \L[ۃξܳ3Q6Ϯ/囬X?$,iq}!zVu:g({M{=O⥭)nw_8Dri~P/?JZsgZG}'W}8N徯 XLjxʽ޽ᦽzy+*tpQxOWܦ_ז= yc*|V?c383> stream x\[~_!lb.(\ av4fƍ-9=Hd3m.XC~N #}w{_\qD"RJEq4۫8Z"$mm8Ep]!i(G3cH#-jI$4L.""FiI!Bxtnf۴zW$Z|AbBg\mp7׭iqR2\!Ö`BK)Zh% % Đ-Iiq!k3&WXF~`TycnpIPLT2,3|TL̏*wW v%Ϟ\2ϲ+]svӏF1'±Ʈm76y%g9pO58" a HOIihcҤݳk]QԁUMH64@_`H`"^bFղXW\X cCqC5ja~{]MDkۚo'TkN,R#b0\O8&[62oyjQH`<ƛ*żU+XLk[SqD-9%X%e @ic] S|^46@ 4ӳfE3a78k\z !2HΤuRfb OK:(§p"B@KXsށa3m N @hBHY~{fe1"twBgKn❫ Y 9Vh!`+4bpQApkpGj#d?1$'t S,bӉ7j5)A 0yeb($AP2*< `S0F1D9&*g 2с>>Y~Y틋b@ո8=PU~5)!)e%Z yIu9N_]'Hdx[^bݏCҺ@⏀716mwN DIz>!{| B&'!IHk+$h+XCYf]adf3XE> gp-2`ܪcIC=ԐPq<ԛs3nF7 ?KfCfx vzA5fq>u߁xIoo[G KaY V bH^x`D4;?-56IYv[_2aAqۏ5~EXlio:"#w-+Mb! =Z[1 _He~QndBwv -(!'1#c ?w--Z&:ס / xx[ۨ'R'Jzk=BE nb%w~o:pﶓ飉]g7|!Wiy水[ۢYܛ EqPxBHjJ[*URV[ϪGtZGЩQ*uBUr VWYwYM֛s\8̘>%&v5|J+gf708H_@<ٔۗ*߲t_i:3|7{jGYϬEp_p]Z$Vd3wp7W;inc 1[cOX#OCz,ݤ)O_ Jd)H]RݦcfV_#PCYz^*+Nj[~ۧI)Ȱ3;P5ڲ!QCcHƀXP/\ @Ƴɬ75/c雯lsx$jfm5(J;eZik@߉;77Ң/{byHl]hgUrwަ2f>;'ŔӃ;Gq]:ߒ|e7<>ƯҶ :[Ͱ߭#! `7ŲigߟQҧk~5H2>aMΝ(5]bWL23~tpL;vrݱD'M EML! Zx'tq3d؄ ~Ru&8dzi1;V.}<{\ܖ/5I/qrd:85ي"҇raCWS`rz~kXdcp3>D"jǸ]^w#֕ZqX졪v_^ "&]o. |"wgVb|jnҍι!{ϸ PcdzwU>> stream x[ko[_A_6CpH6v]4Sm,YI8!h ue񋱩` 8}̙87e0\e4'x>e69Ő#\Dgb.Lbd4 ڌEC q! S"\dÞ RaqJphO9kwڠIhW"ƇOB$Fb|qH#Cǁ Mbb ףe|BW$PheD}L(2:GB\4aL: %f}x3^eUѯr2B_2-b+dDAdU0ɥ<%bIHI>M Yd*RLJX!gRP#LDfL`H9>&KH3X%t` 7Ec Cqz> W0D╎@d_&R1Rj ,yE}pyA/Xa"xƂ&XX"R2O!b.aB@Z㑶W5QI$֮9Xw zD)30}a 4t^TGP x}AB"ȓαǷ\LWtXn&Mdq2<[ ~~xMf26u!+D[%1Ssp`#3|4s²%g?1?_?D!YRK@<[e6A$C6P3; جɂǚI@.el(sRwDD*Eu N04#I"PLjAz`,5} @x]¡ I'A.fJ~@BFOjCplaS[EU!%"ljԟ=4+:C 6A>O6g^8f"Ā d[DzOw׊'ǓX0oY $^YGѬWʰ5AOY`9817mƒ-w5ꪅꆹi D0;eF`VAUnFNdpdiu]yfSG-S{Sn߬RvK;OoVI`<OȷoW)u4vv$_+X J0?ĹA < z;9Fi4~N-K[AvC'_Z_>Qh}Jx+{ LNUGEʅQ`2Hp:B.0aE)عAo_vEp4 V&Es^q(u$Ӄv= fs0VӅ]l7Zl:8}?fݓK 4?/!@Bfq~zfkth3 pԹ;$MSV5]-i,y,X핱2W^ٶIZ]IcczohB8>#5I7Xiwc I#!cl0D/c&غ|XЖr "[@&q^ D8t M+tPB(^ECwp%8J=s0%TWj|gVb4dVjDD(soGW|l6u^06Ȱ! ~! {P( ʰX~J-κˮU_GzGJ-P4 \ݳ`\M%46aݖ\Dr1G!G(ՌH`| 6KV'yy+1fS!wmu 'gP@C!FxN_Op}q= ׌z;ó)&|9,W'ӵtp2|_3 VH) u^}8Y#oÑz`^nr}5\wL5#}㣇9ӝ(MTnip`On ץZ7'9[j2޵U%@H~|c_~^ ɀ/$IP(D.=7(.j{ !u0|G9M) S+Szt%9uԺR+ԁz3,Wԣ{`{`)WXOfj;s7Lzsi A%ǮD*W\g?~0]Oif"<⿕`\zVKb&&7RLc:m]9F0>oU@zL/Fs3}^ݴF,wdwe=TC'!"1QI1\q=_l?|Vlodg Il*8Ԡ<1ʯ$ GYG1rh+xnXV妺>g}-hW 3xuk02*Q^fJRQSW0q,e,X)5TF Fa c{al/텱0^Q؞JI@:f=݉,HG @z4gR% @94{@jt/Iy endstream endobj 676 0 obj << /Length 3651 /Filter /FlateDecode >> stream x]~AB~/h&A @ؾx'ޝxx.I-%J{iLi& M 4a )QV&FH"H/n~PYf'BbśpIW=0hbբ_3* $\$L("`0&y~R/7O?^~weHN ,$In6@>}0Ȧ3A;LH gz0mrAR~2=Ĥ QbGCJ O VXyx5t3PsG-3bXrEB"ܼ\MXm *t=4{,gQT&9.x(G]+5툛R"H?D%U|\J+$Q>we; (>6R@rmڟNyNA[m ۻΊ4U[26@3?hI퐫56_GcGj\M=a*vD[ 336 #KmsH_+,D6$Wr4*Ǝ k.D57Ht7.%blX#*-{~ ڸ;XRzTن4u$ QQ5O"7@Yc;'F(HJg*Ղ{ЬKj,ya_[{ S툙ٳdCn3^;=oNCu;)m@mDL'*6=鵣S(DfG# <ˆBS!5S)9fNkNz=GN9Q|73)5dMC/@Q;g+`Wfbc a 鲸]\g˳nwDAn&P98H8caԨ\OgLhq͇: 9@#)J.j΀(*COeQ) 1:76Y)CR*_ȡ$Ք}OAW}톲:@Pr 3IǶ9p]f8;촍hj|oIqlDo\15r)c7a0>!:͑4kbҼ*"b 9JkN=g•#<ցZZUc/)dWG |\+6XCU^>wܗ ";\/)d?~U<6qS~.q7[)`1P, ;YfʦlR.~Ph9Z=0<әVp-\ˡU8 &!~L fU6uQ_>Wmb8YUz *VP.\V Yc*'-[ᔲWz/3G|H˙* Yok9- KA~u~ ynQز#'<\W&~އsU(UI:Kx:ݴ%?nTsvW}-sԣcHP{1x\ T6\m}Wq ljYG~t5V LBQARF3a.:=X@֔zVf(x͍#a EM86%@. ڎ=Ɏ pxe/;)0&a&5%->O5 )< ӊUT-焝/b&dhU`0@Lk2>(Sď:P?qt&&3`^/][LmEb+A|V10X66K(haWnV*mU&oBƆ$$5JezEa!oŦh,b53G83<,_l9n|4񻝠eØuVDÖΊ\6@&* y Ap6Z篦;0y5Yi=dg?\r]ܿ[xqNO2@0T  ۹h$B/OH.l";#dy.>o;5դl,|e}X/n'?m<WsעxorKF538 ljڹ]{m aG{;'5ڦÞ0 {:7*`н_a0±6!REOD9ƚ4bM)uNISBY@©\6'Á\60r]=94Cgu{bo1~D8V${xXU\Vv-h?.pl퇳h#0Uҽ=3fAn\X/ā^ lUpKcBѭ&=;"Ϋ@t:ׂYAЗ%Fh2&\u,Z!s[tR̋+55_Ϩ3(g Oe2˞lNR=!Red:ε( *lRt 24DӭĜr 2GխCgj1@Q)RCX:Y%a?VLƷ:uXC'TNI?qAx]ҽ,` kRgkS׸v]__T̳M.o;"l>MCg,`q[Kw,Fjm}eȢ)WO\N$O\d?sorCǙY'h=rlj#c9FP8zwUDO&aYna6ۼ^p)k?g*=5#;lyL6PЭ`Y'-e^]=޼z6Yn\}UWff4pQ_Ȇx]_kGcAgvm㣽g토b:'a:l M>#z[4I*S>V}GTI7c7iPoӋnTړ̌ Y+BP/VRо5y"_ "QM%!Zdof OQMYڎ.QK#:OuK @vcU]o>B?K3 g/:WG^_u?e/_T5n%X4]]YO.Jv&D5~߰co|~K}%/א*ݢ"Sf F쁷/ĀCo> stream xn_Ay/FhS$b(dhH6uяHdzl::snropy$3"a,sHo #f o[_9%IC iz1?%Fh@sfHE_Hhqn(NBڐ-[JQq 6[l[XyNCn BTۆ׿"ظ܉CfPQW˫ׄ # &CR278.*_ ~+hDUj-X.$9A6VP)ަ(Ґ #d4u|; yA ث-K5kSm>tV/K6x82no]# z<5^N7ь:ݏ}/Dɝoq0e0T"޻CA\`@O k'P)@*v{Hr&9eS=CDDpGІx5,[Q#ZC_!;, RV!>Eqcdـ/F9* .c0 i+ 0\ëil mCkF nVn*~#UwdYXD8(WKd2L/{ݗ|lF(tR `M&%(Z- BBRHIEeYtFYNh+rJ5}'+(s_,]qY:8i=d)}7ryz\^T^ n,pJoݗ4}Zܝd1fq#&UJVT@XtH #8?~SHi7?㧗[>mʈ҈Pcy#0&dp=K֝$MH@Fn{"nyPąUcFxNm6ŧdg%B eiF`AZ$1U8 4 <^,']^`cן.[O?ev$S endstream endobj 687 0 obj << /Length 2477 /Filter /FlateDecode >> stream x[mo#_pAB,ߗ4Z"9 Hڜ@/([Iswj_DIj/ ə gqtW8" H IE</GMi%Ȓm6D0 ϷnCh]̐"X Ͷ}bQaQq$胵Ь]HjH8Mr%6SXE)G\+l?UVx4oFC3 OWGaL;lp 8<8H%dx-!*HK*I[Բ8zכ*3_t"̪l,Z: W`Vf9Mfߌ΋ٔǛ>?c RH (kMh qe;"Peo \RH$b; ëx_+bBT_rw#Ztp<+H [(ocbz.hϩ\ОBkEJ;JbK(zlUKWO5nq8uu_u_$VE4Y:$"c;0V{R\.mUn BrjR% 7UY t,r%,L̬FM 9V쒆aըuK㽬4.cMV+띆ivg%ӅS7+۵>$O4_#&ʼ_ȷL':| L|ĥ@\6tZdگֺN֋Q6MB$$jla0R?VX+3vwYV O ȿ$7O3ҥϧ7}{5)x)ـAj- ?u8Lucp#%77cD*s]Oj1ڬE&4E%=WG.ZUGy~S` ꊭ`FKLԖZ3(К'_! 2e*NW};$E~$x:krR uQ':"(t/!bzF;QQu| 0@ޕV>:*:w-:ޑ:N #]$jsTQ71~nwlȥrf+ٝOf͞$Q(*f%ϋU-kHrFLkD =?}s`EoGHadz Bb Ex4Vyj?)SrFJge %3$b Ν:11 EID1BT )^)#6 Jjԧ73=ʣ! ;/ 7߃Њ>zQ.Lޱooԃ6mă6d6s70+́4`B4{7C94?C,sȮWKG,YŁCzwfQ0LZ0gq=H Q&IZ04מS7=`'p*= |G| sl:.[F %,WڤE27&Mt8hA<:dFt8N\ҝ`M),6GI.}{"ٗ$+4O(3˽%E1 {av"L*y,Ropl(iTR٢qգ^A3iϨI{΄ro*m cj(NǾ%*ƕ!Aua+w";L%&eE=L 9Q (ł-6L= P lJ"Rd7#ʞO4џ!!/п_LxCӭiH\CJ`Xtv qT!iyP^q aI;ٴl%w6Y*Ru[?֏$#G-SG<Qʑix#/^y\&ƿ,.QH!,c_Zd_˷,nfiד<6 $̞ъYu oa@AAʩNVր@{UؐS-Tk5ٹxީ;LrMՎ #B3jk|j-aa:cMQUV d= K#]#$ $S̆ qm̮܄碷O$Y  u,ffOyaK(h-zZczC%&֝R> ѼܩRQLqUU`KlcסƬ i= endstream endobj 692 0 obj << /Length 2027 /Filter /FlateDecode >> stream x[o6_!4}њ7` MͰ$^m˳(RHrk$LxG {W^`w%= Ӟ QŽO:13i:"'n5ArMw 0CZ6p];~˯ 5<0JlKEt)Ewu@Pb[U9 )W!7Dc6ĭ/&ފI5Xb_(`^_ )!TzgawO$ ^_P}:-d&#Œ}+-TUP΁:`XnU@RG,pH(Bh#_f;o^=%ḱh{^oc1_9erKeqQ՘񏷵j8IFGۅ(F^*-*^keDo*pɛw톻qU9Hɦ0npblܕn٘)lR6V+v q˸l+6[i:x{5Rͣ+AUz݊m6l~V"IJڎ<$0a4Ǖ^R:w Й*'LDL ѹ4^iy&K^D^6nNn:.KzD7̜w:%#P  PMbr)1jA(ؓ;"EF&NjGhMӤzΡ, Ӝ#&<םdORֽEӽEߢ! w sםtoto|o{{zXӕfsŚ=6ұ\w>%;xPIUH&hpA .>Yԕ45:?@ӧB)wwmCݣPw),ǓP$Խ成Smh1x`׌bˁ'4,4b!^\@ B`+Oy yY~qaD$WXfaVckO„1:MgqGGS4ghx~u4 >k=Y\n,L $ dx>FE-ȜHW}6C{!?he/tM endstream endobj 696 0 obj << /Length 1788 /Filter /FlateDecode >> stream xZ[o6~ϯ]ⰽH[^!̓ȱ1JmeYPdJ˲[[ }sxxk;/pr%|!ptbsa{m}kBgv($U3uf'XɊQMRJXs0r='VC0sHW恑8Mdt)EwĕONZVcXCa26|pL(Fi9 ͏YY+8bs\~l|G!%tGNBQ-rίp/ɸ>{A=_*&~6kW(K,pw:#)^Ve)^rH0?v6BS$$2xSHq8+q,CZp/gY~M4^RDWNVDk*\w+p0B} n\8M 'KmN CG:tQ#n$jK'!$Бsή# l$/6^n?::Z7ɟ=4m&B\yd=zHś7TPk5[G%ީM}{zc2.,*:O ̆8Ě$֝M~/Ki(Ȉ s-p?77s]OQhЪ`z,}82ׁ,`3cƒia{1Fl!tǴ*KY9#DU ^[*ZHwԽ< )^<u`"1wmIaW<Cσ5[t`^e8?^K`&( +a5\+r+CYy:,DWZ%ljj ПIm͊Rh+˰v)[>a?LS/ځ>G9E /IPߺYfͯUG#`9ER\a IaVYg|eYFIIŒSÚ6x*ȭ?"T O-vN9:)#m9A ;)`&壭 m2ڜ >dmE AHdUTQ`4;Uʹ`(?efEIWY%:ݠiTi=F!a,4Vi#O eWSsl\OFf\QtC`zWaԺ)1 e!l`\.66@ms1d@5twhZ}hдM{h)#.`AH ٽ7ڽRR$T}AHP\^uQ7R8&<5$whOަ/ [Ksb]8ngE mEռrw̗pޠi`tk2ʊSI,⌵}+%% MerzR{GPqD] /U0ЧwDQ0=6|碷 ߃ma027oO=-~AڤL"#Czׇ#5pO9Fa\,bG`oM^1*[܇g8aE67 endstream endobj 702 0 obj << /Length 2209 /Filter /FlateDecode >> stream x[6nS6.f^$c֖WIrӠ~C%YZv d-"g<~3bp +_GHĘr$vʙn@N #<|tt3{]P-. {vf#Xɦf=]保maQd͡IÜx$ $TSs60/rHˆ^xӅ,TT+p-{CUmv5204 QOjA~q*ՠ!9I(^\=yN($1\+f㉠b O7?²ӫK̉Q R0d*NbCN:Fe`AHuXC]&~a]%I'~^|u5܁x*74?4Z0z#0uӯ H& %Yc>thZf7go~"TUOql,I@'h3ClOsȀU亼'6(QӟEmBuVx aYAsЄvupw 'HkڷDDg8"ܵӕ+6eg葱#g.d]߶A~G)5 *(XJzye[7$)nD;| WkG jϹ.CRJ޾paMose1f\`D^" N_jHZƘ۟`e .L ^dS)6#Z'j  t$5+[D`^q o}B]o e8CUl +N*cXYH=eҔqM uU+77=8>k63z6<vʘւFS]4O5zE,/Ն-);lzkD>}yV v6+:[%[I·I˝m(oD{y3y>ņR a\~Էg'!$2W gL 3g˙N9V۔R&ˑE![5CQ %M#u㴳/uQo9Ob4c\,@˦/N.AN%g͠!.[~SMޘ O}ky7`%0]#? ֟q_ߕQ2$y\8(Jɵ6۬c'w (EYԷ4LןQ%տ:%8<`[?BpsV 6HOL%!*5! ΁-*8`B}k]{v0 .D[ַ3g2<:=o=tDZ1;{bk\9wm|\%˱"<:4Gp8B٪CDOџ*%Ni >*,.mYhL/Q"j.|%|?OЖ_`.~o)R^B.gx"FS#]qm)n9N?rv+s\{ͅ &RۥYKmAkltJu]lVgɽ4?WCPfqg!L>*]<3o³8 D w+$r\pSqjO*B-d?ѓ'H |h cGaYe%AfVI|N=nhyhϝMŸ0 "* endstream endobj 707 0 obj << /Length 1783 /Filter /FlateDecode >> stream x[YoF~ Z?@(Z(P4q!-ѶPL)nrHt,͐]7g_ | -d GT`<37Ay3Z%ϻƷeD0 |k# %"8!MT^N,i(.k"^/$fZq202- kJێ0ېUӼ4n˫c(-`D~eбΤx0'#U0 |yukBt`TWR!.Y!bBa-/&40dDw>%\2/Steh.^]^j޸۹Iu$h{1 imkŹ(nNOW'4r_sXDU)XMsbfrbRJAQ^T)DY)58cBpDY9OB(y)8eZEw1 6; bN[ )-dZV \kݏas(`(db8. bPրq:wva|lTp GRyƫXMc:XԲr%!$_|L8_kbyR}mk'pW ) T>$|&E6O!rڑKƝ=)c(k~ahiIAKHkPpk|< Q죰q-\a,(!.*R@祓%h,l-8[ɋYX n?$ol?E2Ί3!gB-&hQ hW a(Jʻwoª7 *!1y*7w ;?Nw^x?/oO۩U߸8\i_gva\Oр;S ~)6AS8XZY o48fl`"8&m=4:pfbGp~.yVhiĥn !=1fBkM8Wu3 V].Kwb7H}굝zmi \| xc\"թvj}M6 mI$6Cyvce"vf iIbݭ|aZtgy/^\0:JA#](?x@CL*X,Mmˇ[.Cd1Z7MkEy,zor(YT:\/g% endstream endobj 734 0 obj << /Length 2847 /Filter /FlateDecode >> stream x[YF~_A8B!QY'GfH1)hkRuW#|Ó8"1)"2Zn/E-%ÿmGI4R m yjf'"0yn$ 㢙_Hj3Ư]#caC+ǎ(pb)4V䏲β f͡0Qmwgi/@#9i%2?\^,~"DGIet|'E]_79۴t6T?돻@2K6跴[O7cUUZ~˽[_47"zu%Q<=]$ 5z`Qlzfq@}uN%#t0)y:DY-%P*BJXաJ .oQ͚C$]~v, aŚ -o2Yi9ɈHt?b=BGGJ?Nmϓ<",bzH}&R}ZTB3P'OEĚtB 'V'nlә_WIks:\R ȊX!! EAV[8:_>]ղvT(Hvb. c8!91i-+na˛Ԏ?p.tCH%b@eZY>qN}&gprbį0JuVo ) 2Qbkb+,]8 Bp7=AFݜ놅mQ:IE;J޲oR&N7~)mZOa)<`Z,Gc!xRA.pz+=LNx!{ŀ2>IZZyH6x>Q^Np97[~81 Q*)Ai߿YP.|ǺΉuUD:H_/}OQeqi?EY@/jSPҸY8Dg q$v$F:_ x,p&yP54\\2hcE pa݇[8HB-o0yPT̅b'P!40a-Lt8.@ ߤ`;t;:IU,U$?q0W:CF,Hs|O8<&]7;rxkM6LNCjfKyFjH Cϴu?etBqjNjQ3tN|g|;?\)O%8҆Mz*`OP zwu4U%˷Sk܅d qQowY^BoY'̬^,bgd*{\[(̣0=+>(}\ dP? t9s\Zqk T+d &1kg3,c"l^LQamHj+ƿr2"u{4`6)d WQa-0ap=5Hkݕ)ĕWenZF$’HGV}on0v<|q]xbk@unWMn-kd=m]{%=#q RXnH Y;xmWS @59ۀ|6h$q4Nfg $$W˺,ā6,6z߮T|/)aى)8"ݳbYRuQ\o|sYl.-pkt/짿j*բL4_nLFar J, @7vc5d< P3@PJ&A L:H )Zvh:~wl2[rėa/3wtUUWzI T 蛨/Q Q7D^٤:Mؗ筋埽8|w͵e_9{Ym[ܝqXU y]:bP7~OY԰S,@ ?d[Y;~Hzp<]$Jboʏ 7VO%*vij!IWV>3Q_ ;pnKX6جJoWD}MPʳIVcuH+j`8cm[> stream x\َ} Q13$>*LmcIs]'/p+NHB(GFD1ajw7 F$\]„@D&W[mDNOdoo1D(%D0$"'7열߯ A]b }v7aqefj"¡ izl&D/ /7z8H0dNvhƶ*KKh`@MHDk"hhk[vAH&3[a_싏k=ݥy|-mnӵ/S6`('5F\ x&5C`td1G S"%s.-WqiQK%jj5(ЇMq?$t+-Q$kTU tH&n2M҇CYHyuE/a[b$%mKP %`$8b]6P"R(`+-s_w BLUE-1N܄d7>$*ihrahʆA9&/Ƃ 1l<G| #ʭ}+gl^v ffV=w2[Ҽ(Cklq]dYGt 6*YX@@{9 33ETha>%mA~ۛD;P.Z`QQ)Zb x٦!f#a-$w ` n X}=|0mؓie]f*3[՟=Ղih~uO8Y~hf50M !t7HOj@~TټHi5<,1G R:.>9iҌޑ#fq!l+=khUfӚۗ60D iHc&)]bKu*<@#BڱJ>uW\yKҢ0yysu>/LžP%ծ waNyL"~\'ٯ0}y}jokT*Dkq_?~Nk>9$W2&5JO*YnFE?|4-NWck$B3`_R endstream endobj 671 0 obj << /Type /ObjStm /N 100 /First 887 /Length 2282 /Filter /FlateDecode >> stream xZ[o~_A/C9 h'!Qƀ.$ Ne4xb 74BǼH@Q X:ħb>O`1 %CR31gp` \ |..vT+B.iJ\:pstGTuX!OEpM*vfĪBڧ©LNN&͛-yXIsvnݽryѮ.櫷ΛR2i^gk[Ry'g f\@נ֕4g}Ӛvaf+wM7"@P Ė(8ːP J@eL@dYzRdS KD>}DG +AxJJ[DV"G IyֱP֢x@XFX 'E("Er@XZs# @b(ENW:_AD>ժ_GvO_J-#8 oa#1E4. SjF)bC9AwWs;.;@C#4\=[é @E.}YLI7|cDsO/ۦ rvYNgN?ժ]/n?b}i&Dqg^?֬;Z͜7WWҦ!Φ*Z jWg97t׿\p熺Is.֝LNQD>;e0)OoCP!}C7`lSӼ\}ٿ'Xb=_rۛl]rh:If!WTjXnҿd)[ (Y<3t)߷^"^!LuX+ L^bp?~BnCu{Ň 9mHܱ gsL- Z.RE`6Js管AoP̟e3LO5~+ؘ6cGFU` u?5qe-qUsO5n_Ž]e2}eR]Fz7G;%IP+}#ʧ=dgQngQYF ZwYe"2 vGvmtP'2Y,(3| RhE8*uwLY' w\ǸA="ގ{(_{ZO;RKp-A|uЦ/vg}MOT=MӉ-X4#gJKO%k}>m"h}h vqϐَ }bb3Գٯ[ =cdcIcftImw݁FOmK𘇃$F끝E%v>>gds+B`SzL=/~hoLRˬzw|u\f5G{͛r t rnWoWyyuw@z=tXkN_ZdX92Cs5%0@y[@,ɈQXȡ;P W(*jqA/8PB RBs^:볺=aHy!ÉTѲDxʒh?] r6?u~.Oj"6*tb81XϷ1~xxi)^r(Kb<#MRcvxIx,x8ltA2T [ zQݡMDT hS=RwPj5('%*xr=IdhWܾ<]~b y OWy%{;q00fRƽ #ҭ#AXm|> stream x[m۸BH _E+pm^$Ɩ|;|-ɲv%)9>|H: >q@"t @ZtyK^FL+F o+ Zr($94X3)֒P?(XuS\3.EH> -q:0umvR kvBnL WVtdA*(=?*5t4bDR(ŋW@#0 A/g-:A(kqoMI@o|8mRܸ;.$^~O?]܅׿m۝&BDo%_TŻTuc95ZMpIz=PGlIF =,XE7YM6e%y<-wت>e7Cb.u"LM}d#k.U;˄FAÚ|"=\ɮ <-ң ri:n -a5T(9!;B)̅h#ѹ:o 䠫.yժCotm-f LjR)z|˂@A(ƣ>o|6ϲ\E9fgJ\H{r?LCT'z2r9r5,!sT8t\rȖB  '#]ے⒙RcKϛkfr Lh)NtVVRUKb@`-}XFƜ @KڬfQ h KD% <N CR'P/) !ȏr T8h\n!$TE Mc`!%LH#.-Fyܝ^P3_HMKti{9<.Te![+U+PI/D2GPUky`72M.=k _0kokXiX2ߎ̷ͼZ>j`H4lHH*2(NC."=]uLأg ƪo3*Oa r.(1RxkgS8 v$%:|̐)O <~HBT'H54YDRiPT $59NS-y醈TawFݩiչ1W/']N_OaFBFXv,9dΙ&k]ږ%;GxhO=AKÉ5  ;:*R1D'(82[*'GxE,W723.̭  A:sɬɰckW$,9䏖qrMGwt'T Z}bgW82 D P}ڲdmZ0e+ tt&P:N O8|İ >2HدcҐ8@K Jݗ:@kKv8WR1`-ҳz PX2Ivk%7`6A-ZO0bK*r3@P[OU.^;lnq0rs8C@ JBw h2E :ݑmmK.0+ӕL(-_L0p,!Zv更h]~FCa)ʃƂaӂFQ^%)'}vg?_0X*ZR# jFվZ->Olh:xw}wnϤLrhr|9ŋ+S&.xܹ1Y5#2s y,hng= endstream endobj 751 0 obj << /Length 1210 /Filter /FlateDecode >> stream xZKoFW,$Z{H{1`Ա-4'FmHڠ, EEƆQ$7)tz#7AI&x@%4{sH'b\zV8]rIq@QV ^3aFy^͗1Ufq-6[ĺ^-ꎅ 5?Jk/]gPch 64sTk 8sP9zt;94@ݢ\K3D Ox0Lލ~] ^2`h2<,U, $Png+(sSsgGАRld8L˲E7\"i'FrwAh!An6PT XZ݇ĭ@d!6#kâ$ <T@1emoC ?.r8Lvhu+FI>VѢݔS>hT s;mtV,LJ/q B0nX0a gPheq ؗ˅"@&l6`g:L*fa 3VO#at|4tXGtÀ_L`$w7adm6J_ 0Q(=#:wnÆ 3.0O#x|.q X6rգkdJaEU %Ai ōVmCR/`$ayvF|ha;F0Ws,h'Wϯ-mp ^n^)CEa,xZ(L6ٞrJ\ߓnEgI4{?`4}+A| d1o!dt7x.k>fJC`U ׋$MNWN]l&'瀽en*Lb&Ʋ<ϊemY \M,zSSt 3 endstream endobj 758 0 obj << /Length 2030 /Filter /FlateDecode >> stream xZY~_A VG}YyX#Q#ƒnf7ɦDjtp11[꣪D=E8'qD"!c&"%1:aČѯÿw#Io}fVѝ i Xm0`R꧟_HM04%T1nckYT7;lՆ#n4vW!(jeZ:`5j{Y?ug{fDj0S|p7d$"r}H1=̣?O(8ηeoDP.(Go4,>m^v`ߢ ,7? !O:0 1 ze)$ W-F5_I^m_](FfMcx`+oJ39f:},/!;acBqUטe7oY=~IVOu Is,)8mI ({'5qz_i; \wxk!RlG H=ےȊ̕!) ɴBhX)ϟV)2/wUzkEϘ.-&;35==8 cIF4I&<4^NSG"^鍜jM#qq$aC/i3j8: 0[P zTT$\K+0.xz&>sq4.ðB 4<LɮGPLחpdTOb2 M L1UdJz$52?m՝L:cYǖxh#ywQb.KI h*ʷCpn?Wh-)rA&t!_D2wLIƑ2Gu"uQ GߜFe|Z:}*;9Gxy5vP偦EyY{)=(KoCqk]sGqĄ K$5U^s:n2lgeu#yj~vUs5B5ARqL vnt$qTg$X:D򪞗<l!V4LZH)}2ZbN&ZtQcRMf$YG:\oMQ ! Y$,`Ŵd>$}Ot;pp`1G_4_4gzȫ%AN ܔP֔IkRH4*0FTżLMP8mmNdA6%Ú ]7b4F745'UgH EW30Yq=E꿲cg]ҥoKSUb:_5JZl+)|wKgWGإ"ʿvxv!"Y+%(8p~!כŃNľSм/ ]REjh,mt&O4%Jpib<[fF գ~ez~ឋ؛q%uB?';,]vX/X endstream endobj 762 0 obj << /Length 2046 /Filter /FlateDecode >> stream x[ێ6}߯5} (6lڇ$61j[_Zw(Bɒo+'DzMC99Q4hf߀ib4G(g[aZn `Zg-ާ}zZ2&yS*M@!QC\xiHÈzɗyyZ(<:FkmĊXOPqqTg?kr4p(C1tB)Y,9c 8LxwM^J R:8S0>uXO칝ᄌ-y6 >#߾k"2NY!2ʤr V|ݑ,3r4]VxSi$6ڼL 01DO"CD-1DKz㤼3D]Oڏp?=wq~q3stOKsI9Yq{;$ז6*seQLM\KP-U'@y5kt5Ӕ1x⤪SD/&tǩIJi=p/8LpBۃ{It> stream x[[~_A"!xyI8֗-`wF+"eh{ƛH j^Qwn&3> IDDه=O\3"em@ ;$I&LVə ikÍΖ ٺ6(7X%O1`>ADs~ӵD d K)MQ]Wu/XH2~t(< fCkחwIˤz,q!4,Y( Fǝ)~{~BtbT&׉o$WɛY/6eB/]Yy'avv%;ys5CR5zz_n CnJiE[,0'g畫{Ya`."/::nÇcSF *Z>yӇcq>!aiٝw}߅~pk.|KKm<i D7|!R%IMVոH`D17nHJ05,nDAc<; 49N\vTt@(AaŊm^4Q+4m) Mpl:_ ?n3r e|].b³ ڄrZ !& u-Dl/H&?1Ny WC;v{IC+Tz"1j$'e5=`5w{Xo9pø8Hwvt2VpSD1#NTe7gO{Ջ:;,n>{ܱ4b..1EmcCLGΟ^= F"C+q0RDFp``?,%&I9,0 , \ IJ*@1tоA"$GFC.<[a~#a sO/R.nk^LwPNJڤoH)}ܬOM_?}: F0)8 BJC_}_WYS Ipn,Xeo)lZ؆6~pWʯ@iE2LC#',rz>83F4s vHpIb&bJ%L" i_ҸNǟ,bmy0g/["pA>n,HaB('UIPIpB զp"r6\$XLHQؕp.z>bY>A!9_ l|)u_MZX^њAbͯ>VJBΗŜ*PH:G$a`S'(1 De.BF="rn  w.bLmGr$:X6InRXLr !$ )~z'TSR`~}اj:cgv˵zPֈq S:]MR}vY_x!m!Gμ~c-|1}ƴU-1Oo xKѝ#}_Kc m \Hٵ4YG2.:tTj3i.&~[U5I! !s:mŁ&)8Lb QȔ8USA`ryv&HGP?6 2M×@Qr"a 0qk]ަ2VAڔfBr fۡ'ߩ3޲J)GDkȘL֧!c hǛnӤ #»y(Ҽm*òlBLɀVGP !RAh8џCV`iL5:^؂'ԏXt:\.$-_$bZt{a hy'Ж=>ЁH:3ȷ/|k)(l&1R0vxj0>{(ή23K9)pXk@'0~h{dvS!`(YWrP7rv05]'`L !/ٯE#<)cRǡjςq_eix839W~+ٖ)(uY~\o ]{U;:&/>4q#N7L!.ou@Ax\Jv}}`}a{p>%E9 onu֮!sÖFC4wBDrT$%w'yxG9ZhGkFT5vZ\ψkJNn/kn,4fe{&GkCh-j9>*Oߋ*MNPǿ]_ߺH㜔62,>)ma"뛄ڜ܏4aTIWN?s$HYǣi8i^Ұ>Ihz4lɂnC"q*b Eb[\gd6 ۢO<۷h/4mwenlSGzBh7ҳlﳢ\26U9^_cs/ԈB endstream endobj 792 0 obj << /Length 2224 /Filter /FlateDecode >> stream x[o6B ߏpfͺWbˉ]E-ɶ";ID!9/`78}= "aI7 ݳdy]k˝&1H2ɥ.fHld ᾑŻXr= z1hB8e%O iL"_ZJ;Fn$ߔĖdBJ2ӡ Qm͆l~=]z5 aVE`UMac+ {}1zgTz2)j54dMԫKc$6֡@&ZW*q ֟Pw:GouԌrV ~M]O _杯bn~~V^\K&%1Qj!w:mc8_Nګ_2=a5qJv"|O?\eIJ:h$UXrcv O!CKvqILh`fh..^Lh$3sn)/ʕ?6>,>\)||h5P9DqZ.T@9SI' 8ۃ@IC6.37Ɉfgt`qh3FW?k]р 8 -M.v@.uU0P BrCa@H1$PJ|r|]5kЌ׏ Ep ։&{]g),X^R<q,>wn^^r1ZW8#'SǙk[# ,Tf +wne#6 PLj؛O8JfVmqyN"$4FBɔ:L endstream endobj 797 0 obj << /Length 1631 /Filter /FlateDecode >> stream xZnF}W,jK>4CCDjeJjIqE)Mz<3;33G\ANHv œ[D149 +rZ_<s(Ox͐+*z+BnKX$SƖe>1l a kX &Xl>#*0,Vބj TІ 4fZ(ˡNRjmgiͩ d΋#arG3wtz="\fr4rם.(Cր9=MmZP1}4_'5> M%f(KRm* L)1ml؎qC4YB`Ii%;>)UPOe @߭Z&6ow|v&b#x L[q nU\a*-K~<O_WB}(‹W-4ѻ1>\'z,N*M#GcCu#%x_#ӫNj*Yl VbAw_ǞS:m${WeGBK+wsw6Y ˩ endstream endobj 801 0 obj << /Length 1785 /Filter /FlateDecode >> stream x[[o6~ >(@~yl07P`MnmQ(mܡ~EɢmɎkq$ԹsH;DEG HRlB*̍E7:]g`nD 7NX&u$PbUC =Aޟ3 K4* "PSʗS5^s`k'PtcJ-ca .'6PڊGߡ9 .q?5a`v\hՌby[ߢf>K${+o^UKїc]Yt6NPKL5?",V\ Z<=ÓYAs6j[ ݉45JPQ@2 DR@GPȦ07I:NsLs@rՖ CB!^l)2Kup%ip\ ْbK)*t%°=I1}TRfW SB`;Hc{'0Po;pB}reD:qOx}Z!"`N2`SB!2ZƠ"N2ATx4MPMQY6N $4{1LAUE_&$Β=;`=,&_j7_ vSiJH'sA1<<MhZ4( #+/ 41$o^ οme0UV/0Y9-B{'M[ͪwϳt8kzȬ&NdRXsOGk" o? xRQfd. h 'oS𰥿'?4y'Jm`l+4ژIwnf[rחmjڦdj*R6SSքJ$8*FmMhCۍAVh;Pј@?A-D2e2݋b HA˥szWZb>q]oEH['˱Ɔؼ6k1kZ˕*:WJΕBLU2γ/{?].zYMm*ږ?F.'.< ,Oqrk[[n} J4Lb\@ܾy$VNc"׊;&PW;&luDr7> stream x[[o6}ϯ 2`+Mr>VK?D$XOdn.L kps~׹XtN-aafܲO.~n K)]n\mVkGl8h S$uRdUL:,Mkl?t]>tJZ'īxmXΦ/G}(I' Ґm穓M;O3E"F pi0'N 3M5P>7P BL.{"ƖjdkIc!g iuQôi {~46#x~5ᬏ !0ORH<;G͸nzq6aeJ[!pVǖbiۗOťe[(^-K{Dž? 1*q ? I_t6ݥ5#Y+FvKCb$YWa)bHG#?VF ah Vv&XJQTfr6KȏF~|_C2Cr=A#r@m>#'tw T &X0+)}$H xp[bPX49)0kc| (l% E0u~.l p{1u0&0qaˌ? vj2K0$ָe? A k 1ع,uѨg.ys-G0:nucyqA1ⴴ^g^C{σpEKO㨙XkZcEeQ뢣DeMIލ:u\UZ: yF*1Jb:/-M/{=~hfB'޿1ߍ~IU*IPҔ4,B8NuG.(eQ() (_ C%U:80SS THVhy`^ _U8g^ I6]qްdÒ[0X#4j6/"_~x* 6TQ)fE?P& &esO@\jOrUvSԙդgKajM0%f_䭽;묆ӟ[-/~y .J/UL(ePF6<:=r dR`*ۖD1tqӯ&*&;WojD7J9k xn/:펡bWt|޻s=},^ jg q7~?tݯ8?zJl JSzυǾ?g\ht\D endstream endobj 823 0 obj << /Length 3070 /Filter /FlateDecode >> stream x[[o~ Fӹ_%n 8n! Zm2HT.@|\HIĤF3gfs9U_Opx# "xnN>F<-ϑm*mGT+Hq*hNfHldG ׭=IVYFyoQ0. Bm:Z1~7 &t{(q@Hh-dוi+sۂT^PH ?j+5$> ;s*8b\ESE ̉?B 22 e}>L 8fWTP_/io?^euoȯOrn'?9=kM1kW{`iͫEfp0 !*ב8{ 03QeGafAiM-*D[+V ($4(K! ~:~ϖ1(HA(DS8v?/SZ=Y'$?o:TWmVlb?yEVIkӑrUӕ圁hJZuZ]-'O֛U]>y27)|Tq5BZ5 c*pwbT\,wGANϑ-r| VvJ wj>:ؗ4^C<} ҹCѻ; w qlp8'uEsBSJ4 { h&bXnױ^j08 $`I`/(rNFD[Jdw]ɔI7UV28l\O,|\"L0,(eB\96vNdìW,OK v!EH)&_l),YZX!_g!tA-"&%]u~m MikH"P/ ĭy\8 0l48) qL ɒ 8 pzzܳ˽~ɁhA(X8IʑVd !d-9OmmOy An> !YDR#aJ<>!+@ Dg7VCкMJ+ { w j˔j\ZӞ93PD(2ojDhXF VlT%`l}5rALMgk+IBg!0p!* 8 0Hg# ~VR\dm>0rn )KA` o|7!qi&{3, pEB|]>>8qy?'~6Q0 dA A  ͤ!+n(/8N6,Ĕ#8)-YR$k夝Ђ C fm&ݦYZŤp >, \j\Q@#Z !_7j̚֐i -}~mIҰR2Q9SyT$j$bXe=>HNSŭ iR|{iT;5 m(_^jz4Fi(,\^[ۤ #p/1;DG9f=;ǧNezd.B Mª]KfvatÕpECF(ؓ< ll{Y7LPjc 5N4MOə:}^q @[80M1 PNsH- "ʑvwf]"m IV$}a] (q.B)K䐺N#Q*jmx })g`/iƶ:G =HU*6)B$%ysa ~]d~vs#c%l+ !ci#b#!>n涨-?PXjp-T@ B*nIVX=>R#z\1qVo& b-m$=wـwu_,y:a8^Ra&D$;uy~K3Ha8YI|ARiRܰ, uv|츳r-zOpî;xZZS W8eU:Z/uCd#xeC+ E=ZV1nn2Vt5+㜊w[T -4x|t!m,Ow( _I޼LY~&ܮ[\{]}229 [{HkeE""9"?ȷZiJ+IL%irHIڝo+I;(AFG _l %߁/%znQYgg('L3 ;Hޫ2iШ8(li(=wb>zli[yljϕw21'η佯Ф]Twe4 endstream endobj 743 0 obj << /Type /ObjStm /N 100 /First 889 /Length 2018 /Filter /FlateDecode >> stream xZQo~ׯCw9CrfX$z@ q 5S!@jeI}Upw98 ɕ5PR!' ,d#q(\p_CzjB@Q̝D\ pB\paxd 5D,δݸ9^ ʼnL3.X 2Pbx")xЀˌ ~"TQ !T*e+!Rd IT4$SB^#9Z)N1C`٪Ps j)BRI `1StT5t*ar$hVKV)J8[:DA$puʸ HEĴ/6xq,n)%qB'=Zq:<CqFh|=4هqbwØ;ufh`c q!\~ ~ XAd--%X - Xqa4cU1LV`5׈' ?6@=P_Vl*lֿ[D DP]ro "}D{ηǿabvVUxqţ4N0[l`>ۆjҦɛzZzhx0_/롳Bc>OҼs. εt[u{qM6@A(wܿY-|:p\<[|A8,oWW!m 20 mGHs8I\ݱH+܉:rȓ9uR+R/?y׷WXo~WEjOx{/"Rۿ}nG (me-hX"5v%q-vlcɔ4O~\= .q 6S̤< ݁ᱣyRxu / ON\})P^_y!YXl,挻A֤5ӚTJs`墹ucmHQl"oC[l 9?Q=NO+2ԱD7ƒ2OG:џtg?Ҕ!Qb0AA'c TEjyxi]]^ ¦`~;&e.C's眾CD@܊G*C+"J'@d@#T(k+|D.Rw ,"*'@$@{[D*@H V8qǣ$@Ty'@(AR (% ҝ,X6NkZΝ[D#'6d;Hm N mumH#bvo[HPm )dbĐڜ(1ĐZڙTNI)Akm_ a7UwDMO ;=&@jdS+ S̵ɶX f-BP57fߦ6LVVn)Ol^`{z|Q}QpQkkXSPj bmE~0g['>_|jyaD?>{O="K4gEn&[?fK/b5=sZ?chժCۭVN6 +kiCH_R'Gx@gە'L<n)u)dm(e?$irEtDTguwLƒ2e22:6?S[|_yUTK"i8|'n 迃s'ٸIO4aZͭ oP*GR 8lS endstream endobj 831 0 obj << /Length 1944 /Filter /FlateDecode >> stream x[moH_aqH$Y_7|H7ɑ=!~^YGv';3<88xr+8 1(4/O@Ij`Č*"^+Q iZmaWʳ+_#lv!6BzqEyu)4Fnwk/=, 6: '랽E pTh}{Q<'a0E;p- T@ 팠Z` #LMY(Yk%]S ˵#ӛ߇kw8MoovUv]Tf>^UH 5ER$ 5aA 9p+eFKDސf\MЩ I1"̺h,AZHf@jH{ P~9i`xTӺ) wpjQ֔%E 3l(yh!ɨ*ľYlvKN-q& ł^Z^0!+^ 8SJ4r F-5 5 9$}YIUɱO6l0B(Tg)>rcۀ_=-,zv{I6͞.sl7S (\2cǒeAevaT{J  B8 #s=I%"[Nk( 3s#p@i9I %i^,ye] RgDa*"QprXyL4;T Dvѥ1Czql1 ﻩS=\{'&%T6"DqD t SK8V\@-Ǖ0+'܋#?^ɫ[VnH$xL`wPN}vS9;W+sfB-kBΈ X>SA+i\+M\s4:mக~?P7|ps }Zg5aSEѵTǖS0Ofyvy:Lss\b~NJ{:l\0a:l[F`=hF(x Dʍ-RVP^\ S~8Äb/RlQ BS JJ-Ç)N[?h٥ ZwZ70kz{{'}#ֲsٹoamP/tnJETF(vBDjjZM0?ǣ9ϺMuDI<߇TdM>2FiQCҺThU`Z2:KDn}oD LXuaIRC)*,F)P,}6//$*'̴94R Ed=_tq|gj | f ~%ѵ`kfz\\44AZ( `E}?%@_ѰfA s;|_b2!'5}&I"J0MΈΈΈl;#t)/2I߳r+-WakVke9lP tS"6O6[mJL+ٓ=4ho$c Ńv2 ѸOqh>:K?}۳1#':_d.0I}׌E/s *$YM$zgֿh![ endstream endobj 835 0 obj << /Length 1720 /Filter /FlateDecode >> stream x[mo6_At3+MC[-'Bm)lw%V,$v4Ҙ99^M")>)&"I i*1! &G#=Hrbyv1&7be5h$PbUʞ0t̄%JKEmcPVKhX82𥒹߱  tUbw(03n/?h&jL3)9tYrV֮ sחSmV1z#TtYhQo>vF85 UN?~[prJi8\s̘GODlc4y2M޷|W Q*uӺޡй'AX\b mjTӄjÞ\R5඄2^(lKa9>ΰBil\_E/ғlrur' aH4K_G'Wqlv_q.Y`9n1M f@ DAEDl xu*]- mP~"ArڀoHͣj n w1]kl湻|/i4Vx1LAaلtz flg&Y?NKGN2FBLXa0 s`|E.C`1uc& 2)eΠG^0EC/R/F4 [I7Xكm)0n)˭p0VY)V'觔vD Bb=[y8_K V+D%jZNVdD`-d5DDts7D7-WJFnhODQTaҹL Z/j&UF_IJz=b *~e6q\dmB +&KSc[SN߂3V(@@Σo[e$+*ڲ mJPGF(@k+7B)M1H-bwsP98L+ ܕsEWH9nho `q2H?{ZTNp&ܺƆ[oIȷ |<'BETL'eɋ4N.60lx[m9e7.b.9szO@z##mאBx'W$ه7g?[Rgi4{%5-gc+si &1&mpA~85b+.B 5ssFK ^DX"0",aO}c?LaZ-oy99cF:<2H>޲D,6tp(Zq`ST(lLKcZ(TyJOg,`G⮥ʺ^T%(hCH3!cU"zWb0w e=#*ܲf_r/1_LD mB¼8^ ܥ(ˢ>/8=3=1$4.ʎd_ J"5ŗ|GO U)\7,-(*F.ӉeJ.`ozV?2 endstream endobj 847 0 obj << /Length 2750 /Filter /FlateDecode >> stream x[YF~_AdBv߇8x7X#>r$Ό6LR>[%J]'+J>GO/p$G$1f"EM4Y\-m/mGGÆh]̐&?4],`D* ED$0Ư\#cOЍC+plGh-OƲRAwCa0j )dxd$M;)j14ze4&X5y; *b6z{Uj~[㰯Qs2j6oMjܰ)O9B((SD"WwhLߏ(}5"-VSvcA8D$hdR XNtYQck{Gs1S~,dR[fcOٺXe /?¸'?`,dE,l9M?~] fN3 G蓚!ಧV,G$ߛ\3_LxZnXl nJ?&wd̋$P9+w?MYvDTԒBl48s9 ✁q1u/8bޞh,йh,o Ҋ X,i_?˽NJ,|,`vKmQLX(5EPMʭX~P9Cјq0uLq \Fg=;3sht b+hi=4:{BG-:#0xH>[Y .هgނixgec3Q 5Js[RB[`.qf6CESdjPC<#u qݞWYYzj:-@՚ʖ0,-c/dN&[,sC@C÷~\. ZPAMֻ-5vU<~8yR|&F:T".zdT\7Rk؂ {j,(xPnӲTܵ UMu*bEbj? "0 (x`*3% XQ!~)9=1K{1|dvi!4ߟַb'$d!HCPum{)ڶb9o-@`lۥI>ZN7 ye37<9˶,8v/FC8YRyn0Ido1nS_JUoƛjm_"|8yv1Ra@’XlŁq#oJ?fVSHy~)\q:S\օ7r $6`\p n֖˴؀vH`8Abm1Pcf1և¦UdvYnY]視e< mt# a&N8Hr4K ΃JX^{dL@J*;uHʰCBa# $܈P_*P{]Rb8-]-%yO&g/K^U0FY@Lr@&Y @N>Q(0{4*m"!h{2 ` Iݙ\&8_.!"u0 K&l} i 7q}<}!G2] 2:=N4ܥv@wɻAY>h.կT?2~b}`||||ZG[1$Z!DURCظ{[i;to]8N \X}v_Zh8y~ ``CK 6pRBxzӼIl8 @}"* _EbUfМ#W^N]iwd+;xڇbUA(8תcW_8+wQ ۽ 'ݸ;DtfY< SߋuxBb8{GE9{HW(Ng󩑰.LЏ2!@b?~hO(ƚltRUvhߓf0eݝp2swcE:{ݟF\%IoWpR,˪b?u+ endstream endobj 855 0 obj << /Length 2576 /Filter /FlateDecode >> stream xmo8Wb._z_a4a8(%W~EJdNH#eDrgy7g_ AZH6duʔg1E9by V[D# 2:!MR7)_40# VQu]5"ȅ%&*_HVyPFƸ?YYTlvč&6 t52AT=Bf?jk'ӣ:⁎91IYvξM~Iet5|*E9&F=,7XP1ן/W?j~.]S޸߻(lF[D9H;/s:彜 rqUWKw:t#i*y:\*R2ah ҶӤ3x4 P@iֿxE:Ynt'mJk,#6mAe- XkjO"TZj  }ڕ?@((6E^K6YYM&W_nD8AV:>$"6Yfu4$.;+nI\Vt{(/_l\va,A+[[;/4u'ŀg8-aaCPÂG)E=krAnqzLaxPj+Ks^rQugU_ :\qpώ=HLEQ3yn2SG^hyJj[z]y`eB5zX"}nd3nK֭!3e҇1>Sr]:$C UW4Յ?gm-`j:.{@{x(FơQWڋUAD j:+}TpMǙ$ۍ~K$9pױ1bN $UISal lpj=o2CEX(Kyu?O:¼UUVX"}k&n\ endstream endobj 868 0 obj << /Length 2656 /Filter /FlateDecode >> stream xZ[6~_! F42fsvM3IPhlyƍl9&h%Md{] dywxn O0b8 0$\cĄYo.^7h0EE9"TAB O/0HJ׋*DQxãyͶML?^(S<4eݘ_I,ʽ͛YvnactSpm؞x8;`0qe5&z1`fv<>0E`^gDd!gvv])ybUCEA7"!a}:H6S3צ %.9΅u50K0lbCzw)KL9K&$pXBp\Z У`+ipPAx >9Q T#wЩ9(}%eoJBp :(x;P>|7& ZVeլeeulZM6?s^S01PP) P/AG jIU c50I=GZlgdxVkCl *!.Ola%U6% m4+Z' "J(UMoUoŃf6| naö򡀵@'Y ]mrђor}{S>,܅] &jkAh#vq$Ҭ ңԁ*iQ*I()S?{| U|DjJeJݶNd*:|ӂ䈹¥Kv!JY~»tw5xM(‚f2 [oW1m ̇Y) RRt}n x 2ᰆ7OsDlD")=ئxt}hffQbT'$w@^{Eceq4@&*.?ř{-2ֽf.pwʼwdfBȨ)TWL)?B8B3^!0`?zǣ9x4#6#h6>ru`M"˺_W6#E=׭W V;vӿB&sDYdS+ 2p܍^F `r>ĈqPp{*'\XBu.xOTktgAdtB _2 gBzG7g׺=kF~w@._Wl\x^!i[)FK9KW(6IR-cYm N<^D$W/௾?ư 8t'YM r^wwأ9%_OhYOVYR? UqULj=l(aߘ}K? t0.gZ a48ʑ}yh"c\)~͛ K/c endstream endobj 874 0 obj << /Length 1600 /Filter /FlateDecode >> stream xYF¢IvޗNS\T>BI\88QzdmlFtRۓٙv~k=J{).<R&+{#xF GίQD`ˏn%7{Rk,4 X4)'`xLjKW:Dfk#m1# 3z#@fv}xterpn˫U( ưZUfb׽,)/>"4_hQFZPg^%$x=~w6a g#Ne,I Fttd/wbD|o`h $/'oij{=cNX4̶jcT= =\n֙Gsׁ>P^֍uVYR:YI;燋Z&/yQq~t,g ^/*v('o:wU&[(]^L`Y˚4l.C3 d v{g\mHV_ YM-Fi6E%iWC!7eG+[+S{y: g6*zy|38}\ypu۟8p('W=:%n(ZehZ.7pDq;OE-T÷Y@Y>Bu̸ht/[nwv)M'DF9,3sӧa.X~MC/Ҏ%x4N({ 6E<󰉾;eR6h[K^EL>lg3t Bb7gC_(atfaK}{p{M+I\Hs'c8'۹AO&JS齏=Bҧ@Qq `(k(_tGPsԞ0Ԟ0 ԞtfK$wi؞ѽJU}e {e(6a֖{W|nG&,:FI}Do ZW+(ed/NRPI_-IVN`}O , iߜQ<܆Y?| gb_!+xڛ,yi3_TrY؇0:P(? IWثr YD -MgqnS,IY endstream endobj 879 0 obj << /Length 859 /Filter /FlateDecode >> stream xڽWn0SX \iƲLm&LӴM N@FȦi$i0e8?;n*XPhY P qlr`ArZ\WBD|:б ,bhմOCr@84c;eUEвkSe( O6)1`QS.Y~΁WTр:qkG8;]1e. !tbkd˕1^}߉dt. ]pm$]QR6+_p5xNn|Q[Y9r5O 8CF5 w>{Wcu0?2"l΀ }es`r. hCH5 $n춍0NvpM&}9i =:0H53QVT1_gC?vvuKQ9;QnSWSi+P֨Ayz/*kePb\U*%O{>]aJbo E(z N-2,[O c0҂zOw&W>`BLIejo[gH# C]Ke[, `%wҌG?TT_ endstream endobj 883 0 obj << /Length 1551 /Filter /FlateDecode >> stream xX[o6~UE%`\C[LZeɓŶCQ)RVmGN'aW!'HraGwtΝJq $w>:Z KW+"p!!cI ICAث 8J#XTYss`NQʏe^eD#/>~k+h+5lFY/a *b!=N{!5#! g<l2%! PSߙ̝ZIP 2s޺ߝ'5"|]ɈS١Q4\뫟kuI N>*-,az@ U N lJfh{"K>$QIljz5N/::SYF._ק@djuqނĝGXR {/NWrj5̳ͪuT=hv*ah]8]`MQDS\%jA'PʧQEȳ2+.x~i9/F́q-%(Ŝ;DĨi &_C5 EzI&,Gg8h P(K dOa\LYW0J2-f 1N(Wa '4=+skQQe)2*<^Z*;LVз|gNbp3Vۿ ēpܳ'o1O,+rfFN(1; mTNpĠ]C;i (L po 5323\yT-]Ԋ5[Z "Y|˅SlqIy,hB!cUy # ,KTU R5B+:*Gss*,qXBqfQ^Bpu*(@y ac^ X tK NMx2>9.>ᾴ *C&vbOt_OzAP}14h>;6QvW'>~9> =1%g3ܜPUY{}K]R0}gqan K`{a*qwg5Mh a9 | nTnYD4UEmPrsؠ!㻌*$ endstream endobj 889 0 obj << /Length 2386 /Filter /FlateDecode >> stream x[o8_!- fH{{^[`[iEc]m)g Y-۵`MI?f8ߐqt%qD".:#,(_'N"#"CMG|J4T0͢ )Rkja:WtQ`0eԖ??D-vHKV &v+E13:-$КNPvz6Lj%BF#1k?\\%DEifN21ut3~eS-t狺*XffF է\e8H(F7뤘lQnN/L$Oc#G(4i+y;K'I3Ƴ(7@CwsK{s | a,aԚ‡(Bh@/D6DIlCcԝH?G2aHZֽw#@.G0q9 jWEY7kOR'R]]_TMrruo*Wx>#Kn N# dH`ɘGi"]%F ˮ9bLQBq|f ?wF-iIt<ϛi5F cP-ax! V&Ϲ ]Sw] Q aFc@];nEHD񉈳tܕ:MME,ooJ\ `uVjZUVM;CLۡEj0a3A!4k2YD sݟ p.x0> "m $̤}CShT!I cBkl? RcHऋZAR(E;39NS8m9Ze\-nEүF*{ r1t7<.!] eq.c>/l"L*"u/q7f]VGX4תi'U,%dG ,5ǵk 6S$Ϊ3Hͩ+5,w߿^6EUz&.wUu7!ژ-܊C\$Nxg(ƐOnsUh#Pt?8Lv rƳv.*JQf8w6ӌiiuc}r yنyZv?ͨrM3fPAƼ pU`$ Zn(s%z<-7%b/Xrsg \ ;˅Jgnާ˅^r[.Ԝ*oڇ+e:I:nl-BxӴq.\Z`Iٱwfq:KwN9iRTKO꺸-fExI(̯(КP-gcWQ^~A,Q9ؗC)g. ЧH5qƨ g`xa Y1g{ofkáWL}@#HA鯺I(LǤ?÷1!CeXOef al`ӀIq/UyMӲ箱8r{Pk#A(8  ^z}pZGn_<o]ݏV :? G >;5 r1n:t[㽯ykGA  K [/DX..ȶ Z;qBnHmnhn/ h?|7z?"v s3 OPa}F4$b'y 3>χ_N87_`uǿi1ێVX~ $7`k#iXĉ}`@39k`NF`>˿Q,?'l %'yj:p#6KsK9H*L"twb?ox!nNV' x p=AI5/g^2{>Q&+J3T>aq8l endstream endobj 893 0 obj << /Length 2606 /Filter /FlateDecode >> stream xZmoܸ_&<]{9\їKw`䓴qk{o(k jp8<3C G~>p 0bq8W>uG߼H(A2&%@")GtY0DR`c*TW%:~wno^Sͅ LHD(C'=-p+vYthz_ٟxG!o٥$w5+=21`jkj`3qQmnC7p5nzzE;01<ݤwK,յΑwWU7FRmdSURX""Y$plR6OZ8(`6hyTCo6 T{T9[Q $P 0 W&Fe4Q^rÁy3r j PuWC.q,bL*ĝ8sŅp+Ż|#] ٳ$:A2LbRnciMkoնZZWdS+aQR/OjwvkIpRuF9#w9cy "E@f8D罊t>һ>UCV{<\OGc&"Vۣ"92Ġk&"t7 :g)#5|4q1E1DR~w@%d TWZϳggS*"kSԬȳtЍQU5*E 衄b9Iw-:?<SwL"qDARl>h^<`w#9c @@Gq)r.q `DAQ:>(`x6\}`*a1"L@ 2߲L?6`*ar^%ޟ(ZUYWmD(b6ˊv37bݹ=GG:mU@=__rxy'ɻzSTY;%*MPz .u;+as|=W1ADܺ:tc"ږZxf@Lo1 ,PQF]}C|`? _}@%'dj!AغN]&zcXN*Ngm/Xv"+߂WV7ߝ%mui?7 +, -g~^jj?VmYxq]g_ՙh椢HdȬ3) &y endstream endobj 827 0 obj << /Type /ObjStm /N 100 /First 891 /Length 2059 /Filter /FlateDecode >> stream xZo@\>?f= Z Smɹ \}ֱ߬e9-[宆#8+\$ƕ]v/jJ>~ԄQK]Lf1qOBEZ\̹ 5@ 38ErN.V<B5CY&Hr9bcD lP Qa"KT6@ =VB; hGfIU$P ' `JI?QtY0%^árŌ*uR1mꨢ`C9#"h&1e4X99R3eq0 L:GQ`c`fl8lE;cVK F/[v~bF.Rtyc73,}s3KtVpBti{~t46= ݝt}e^^Ӆ_}\ F~X}찦bzyZ/><ۦ(e+GemZyيzmgQŶB&iom#2ˆt{3w~{EnNn/oZW6"kmr,=o/J[Tvx_g7ps05N4]t8zeG7X=#o !PE1oʎ%>VGpNM*$5C6Z6j9[jݭ5?A i9=)2]yR2)GˤeRBӕF%v$T1x҇ē?ŰW0|2--̇_}ߺa~٭zże70g|u\+?_/??{wYiZȍ77 7y 4+C(*> stream x[Ks@ei'^9뵪rCYS&xofX&p܃c;$J3iA%px?)w:8\JHHV.֧1Eq*w3ʢC]CJ08TvLQ+a[ЈJr<睛qhJOZmE$[|4 *+\g7j|mt?Y.ݔnMoۼyn6nPP#n,TUzi'KE9dn\`|Zc K DUmoQڪ=c *2DL(ۏ_Ɩ2t+_;`OD4!c\>V^ol2K3"z&^xm'*a[Ʊι΅3ew;'̫(I]މB/ HAP|BD >"x ³$Kr_v,Dzc "^'Q p'ƅ\f:ʅ\X́#js ) PDĠ Cc eIb( Q^XfN·:붍nJ~Jq)_ ԟ*o~tuĠUH0EJXD-jH@#EQ_& o-bXE5 ė&l%|lKCDX0䍆 KӘClzTU-Y>mUټp#li?q}c(wlm/l&i6v["NYnl/;e~e8GZmyq3T3[!HɦAZ^5"Neb<՜8moٕj(>aJ+H2P.*+d u&it vD" .Zwݦ}RxdA7B˺s3E]]98SخVf&Lx-ܮ󫇞mڏY IRZK:W @(u]E^3(8@4<ٗEJvoʊk]f}. #(͗.?˺86df f (HIc`*D E p4HP4ӡb5G%ȀQUqGl{oLԓ٥m9לZk74jzq՛{) d5 1d$8`8?KI d yHb<;ޮn!c 7uR.1ִ$jkU&b2tUn>VN\&k@c~#wBv8w~_.P r*ՃD^àES{}/x2{!4ܙJ$vOL^+ -CcXa*:^쾏to2^(z-dWWWySW:JwFi1| r.|xŠYgb][P"X{#(tD/bƚ|~0F1ض5,i7;۠ˀڵ`0AŞH˛*+<yo0w~qBXJmU« VsL~!,3l1@yV>\Z]lwӪN7FwfO7 C]pWKyl);Zյrx[Bc"#g-9aЕVXW{[G}0爽yCcw$1nfLq̬\O)hh%F|' őG nzuQN$ {IHC-/|:$#ܴͧ&iͯCD/Ԇ"jɚ"T^cȊAL]m2j4Yn1>߳%Or֧fFi 6w%.0&6 NHJ oK]`nNgvpqt?vG3M7w?1 endstream endobj 910 0 obj << /Length 3263 /Filter /FlateDecode >> stream xks 43' $CyqIB"dG V.H}&ӻ;X-b_n]{w,/<ɂD*/f*I-7~³€v7,F%HzLt9Mմn]p8Ѱ6qL6ᦉK N!S鵾#tmUjPb-PyٚkI0s^ԯڮ_Q,mLT7.j8,aM͖6Djzh4[Fyym1)?qqZze[K+Kv*j\]~>ОEqhh (LhgA*7_R?hַԨܗX.%\ Sd=}/㳪\FqgyXjmk̛*{ǟ WǑD_4%i1%$U}s ,tޖc" 2 ?X"RK6糹 ,B%s@D53(k0m"aVqBp)iEs:(,4bht8Z\YkB8$Ӏ8;}x- +NHd!He4'$462G44 q|)@l B#Bõdؒ4`r^WVSR1OG:mvDDiM86[ &آ{ )2T0tYt(ES$aL@B xEŠFYЈ>FQmFP 3c6yy], 0xH\"jmLrX+?S1Gc)N"с/&\=V5 !zC~*oLmycU[T;Sϗ!.M:`CȚ*+|I~eC_$I3$;&8HL$PSni)ylIX2[RYԤ|M* v2zi˵Kݕ ՄwyJ^}ur&cW[UB>^Zd]4ؿ*į)ۈX0PTڤt ꒊ Z2KAh"[bjQ1ՋuvB0<#UCrWIZ%:*ΘMێ) u{GD\]9J@!Q}$OAnvQ`.8Y"uy><0zV!aJġ7qHOUO""SdD/Stfh(^i0I ]uEy{Ku}]]xDviwvd{*RA1xp-<p$h** f@oq5H9fT۟xH%M^uVM/r/h*:DW0wUWPU'UQ0j`NʑQ B?lhɁye[w HZFpT `7mL? +]c#0sZWQ[B ޤ,vuj}Y%ĝ4KஙԾG7uiI?ϲ/ŸY_,3{LÍӘ_ Ӟ 6Zx)h E|x;"L@!NLHƻ."rr/D`B c=jzo;N?fs)"Xa* "_-j_?9Qi' &Os<9H endstream endobj 916 0 obj << /Length 837 /Filter /FlateDecode >> stream xڝUMo6WHEI,C-l==p%zW]DcmΉ3͛+`V<3/4F~{VWk!"J0yU1c"* GU}@7 'T)A'mbѣjqB RғwהH`:@ 8R`W=5(wgc04ʶt9$߶Ҫ&M@b̴0,1^>bscgúm^ju;IAN1_VBʳ EQ/f.ڹ_T0YNZǿ N\O>VԨe4jЭȐjȗ8.D%Eʇ=kص''-QWA7mU=ڃ\zR&?F3 >(|-#&*i e(A-1[5zQwfz.*Zۿz2ޗnYR*L>\jU iZA 8ezW˸KmӺ}Tr -yіԊ1'ddϧZ+8M.w;|asL970L4Jrw!#kgN5 %24bvz"58q70،~ A܌J0I.|4ۻg5M[V`㌣e6^Ʌa]u?l endstream endobj 933 0 obj << /Length1 1456 /Length2 11632 /Length3 0 /Length 12632 /Filter /FlateDecode >> stream xڝvuT{-\;www' 3;A ww.!qw}[zV.ի4$ 9;'*4t;@Bm@ xz- |HٹA^}:. / l:ڥ.;[@( pwvqpڂ`RtdgH, vV6 V$+#o$(  + @nv@Wl+ !7?p_tٵzZjj:-Ym-EiY[y! ke@K_VnW+kvn "Y8YJZ:5ق`鵀`W_tY }zC^}E9CA $l\FK&# f}?_yڂ@p|k~ѿlQF]otߜH`rIor?+ҿ5\7 p:u:/@uh@n4|m y+ r.齎/+:[:~^9Z'W `FP&QQ PҶ@k):9z?" H %IgW1q*gҰsX_h C6.N^z?rߙs(ȫJGR:le/' o,7=_ `;:[m^@ `~w(Kwuk굸|{ D]Y[2+D؏~VAx2.[C bK(% cAֲB~l@'becrJNxPqE\%E3O O#!kN:v葵 m1=upm9L*)ܘ)߶_RV}fd[1iykƲ}ۀ ǻn 6j};G>On`mAaϰ%V@[t[#RiBhnT|`}uF| 4 R:ゅk)̨Ji1$ޖH]]P6 C~Y?q$d@zogG50 ~rL QC{vUx$ɓ" Vldo6(];ś!T?Tmr;٩܏l~ !o/9nAT)Xj{lsc vgfCѝw *\gla麸3LWv#߳ĜYIdr 3\t7L\r6J_%4Ycr"de6"./W掠 ia!y,F$ Q6jbn KUFWAmʷ^~^;11j O~:f fjـKUW/VtH@IX fP,Huf~ľᝩ:Rx)>ӝp "0|L[}F1'}2L# OBײHb虎gH&EK_fvcaBh<[՗{*Z9#'R}.{P@SeIYFJLucl^S RFqyT;O%OB3凰2 i&`>PeijbJ;``uzZD84tC.ܿk Hy:k9x]G!CoTAZLz Κh2}Y^ATpł:5F9`U]x'lk٫ʹVĔh=k ?N/^LڱtF4Yu.]WJL=]^ʴYr~A\kj V ;H"jk )b( .oꂻm?"ANJٛ]- k e5֪]T(>>;]q`frBbMFOvʺ!QwI]Eo;fx@-CYuyvJR>{G*G[3HZL&ܮ6&9EJzOZ~'[C1)&hR"uD2C_wFy}PM3"D; bpoyB?@'ȡ0x:eetIUIkI 1JĦ-Kqyo9mf4mn@B|1ഇG2xDSp Y_HڂwgE*UceT`6M+X ka;1(ջɯ'>1LtDVd@8Wva\tMw?# r\F CԖ Ocۺ(OVi6qg>HXjY`Xr.'e17x'u+iN~?]rm 't;ZXEJdiN_f8xJLkUGLDIH74[fJ[:mUi&8J 72u#o1Qw p;sSg" ::`/\qzm4y R%&{[$k] YĊL|>(0b{%PD֔Q:u\&пYĉΩZ8V6 סVGⰒ0ŌL1^X=`FI|,:Ϩ茐5CeLJh0uq-{V0.ʇl΍QNTu9jnuE埌|~$}HNܓlY2wZ'jC ?wmCO3lr P^ (.bJv?vZ߻12K؟wN^gt4V (,*>IV-vVe("k r^TËu?IkÂ畻nwh5 I>^ KR3A0Uhr/nj^- BIbXYcʖ؁)TKiC]JiG 䜞\r9 qfϚuxR!Ϋ%-Nh<~an0{k] =\ƀ\J,pYצVf_m㛽s[3fi=tT\]*䬡kIddVJUrPc g:B R+u /jO~"KL}!4gHYW _Q:i ˙C=X Hʀ\B#هս;Z%oF}$3w'ՐZB e%ű^з8 y7\=~<|wPg083j#)!^U+}IB<Z3mrn^ LCLB!)WQ]v& !rqd_cu-XfdF4Ĺ Wb?g۴tùuX:~;;V>:%ݣN<`Կ]ckW,U |\]e?GFi( )nnU`푓2؝O /tr9zY HaD8ݡC+J{otxL(^- =(ʧDAN$m")qVm@8g,7t^|^ ѓ g]5_N yC!v-R HUA'Kڰd^ n^L_]a$'1췌hq Nq~LǢԐ9?^Tϛ29l Xؑ)'~&x$LQG=0t  k ^PNAL}S˼pTw~P)rB\X9elb6eE}8ĸ\f^Qc)9. pƇ&0<(d }6C/,ö7xO}?]1PqE}ûD+n%yubZWD$;isH KUq{iO n-dL G؈z;Qj{u7>42;?SE{?sCˉb5Q-ȗ#_KtM~$BZ!?v=yl!%ǽ)E2f4)N2W5,3ʞS+(د6BD~d W_v#oT~1?Rc EiC^;]b$eU,?vVf g~+ -{V66e)W\TJ^$1z0J(_ސx.W`tNƦ^?Hx~+#&!Ey`݈\qrd~.+ωuX[4J1̉.P/߼x1{?TȀi;rE㹈*G-"z3i\ؘ*cՍIAX#8Mַ7 @n+`d}qOIR0rMcy%kC!HͿb=_pH+W;lh {{9ikmwI-Z% j} h{6<7rϓ 8V m28pAԔ8Q*6me0N>\g+vn$@"F1e|*}Btzw],o k)0p6/ߌ]E=qnv "<(bH(\|kFd=YB75\ٙ(Ao6.ըEeI3ҫ- a`L"4lok b0ĕWf=ƭM$b2iJdQj<9lj]{5Ҋ`-[*riQF$mNYZ-@g1pH9a>{I| θ]wRK`;ﳲޒ\vFQK08k+FW+?3FiIa`SF)9amp]jJCFiJNO/&gT_n$g:( ZLT\LТtgEp0];:N:%U1`sЮЛoX9^GF#p"P+'x]G o(͕p'+Wn)<@˪ϬOUR.E^h|ao/]%Wh/ZB>mp^} 5i<<;1:Ln3XAr B>z*VP*&C%{Q*w~Z6 rH^G^6}7<{+WJ29$UXh/UbZg8DM ܁ To~fc"\9;Rti6ěp 1Hڿ#SL8UpCL%E҄&>F3x9p J?>0")g]:XSf}|GH[F3cFbfEf Nxh9kp,Em`oCX$E(X8I!4HYY5 Omrv$Uw`NErZ~1pdX?*sxH2(rglq/4-vVKa:EdCTLݞ!rD o9P|BFNt`y.xټsB$ -fp CN_isߖ6kj2{\M(’EIu:^kIu@ܰ)Ne|}>}ȔyMao4なZ.3cui%;w? qG4^ l*@ƼSB,=*˸}p4'9%I)GhՏQkIjx',XF zFp:Oi/\ɏhzϏ\R ;n_Q(q׋JOxٌ8Nrָ^1vBD<3(g,AL@i#/V#Obϳ`L_h/&}LlGC禳5~#Ǿ^!"U l:EҀJl7Z^.CهNK֐'QrK0d  ]ʑNS5[7ZT1ԍ3=c$C2(~͈H>OSTA(VrRykJIx@v7caݢ~K]H(9˞ff j̆$y>`VY$2N] EŢme. Ij/OP-r7[2Me?Y9Tk'P10N&'{V9qpsL֤SQc#%+UvБ%%Qz7ˏϕ!n$~[ߨPoH/X8F(cXeUބ_xzvk"ьsOc06EY?Ru)(==X{[KG:ъUc.ʑ>3WK=7cwJdLBgϑ+k&kX$JD|J4>p~FқVZMh-ڬo3\âi瀇 1._ VW^Z~NduW;lWyΐy4%dmP3ߋ!B=&P{LGM'*=94fg .G',$P[/zY0oY.~\K[ITb,I$+&Ypd/PuyHŬ%9ƸfK K὇Hbd$ 9&5eFYTMmB ZIj؃2zpm@tgakvD`@>AXbx&\xo'WU]te8^ә['2P4lL2/|$N;q7x7Cڑp Ud,E6&O5M!7d4#hj!R q?Qg5S>C>Yo~bқI4gν-~`/O#2* iō>' $*̀4>E TyJ2& oP58>qȕ(QozZ*LZ3!nx2:%AUF[Fc!zxBƝΞG-ď4J{-)>;}z4mY;-{ Z!2fxp A< <&^?؎0k 8e JI>kiLɣxDwhh3;?O}@)%vBC|M0]m xƮdHkStDE hJ:Wej*'?Z/9B,rbmZCYʕq>uQVߋ,})N죮>?[C`mixo1?+si>Xm%o:;OpP*;G Y4~.:+XBٚ p}DHJ*.ۜw3 soJZ ~͗Hpt÷uRR~[rCN4\?g0X@CGp/4"0єc0ܿ?$ʲ1+7x0_z ˰ha9o~SC]0GokKݢd_#0o)gt䟒 ;TSYk*2:E5Cҥ7I L:l KF \~ %XLcҴ` <` Ւk?%Mt V%SFB,w,ӿM10hAVX Q2`%<~LX'ˑE봣1(m-}c[ JNk#zdr}s'.b"]TM xq Pod;b.b*6dU enR/,}$!\UTmrIi[ֽGgZ/ݍGJ%"0"H,6E+6JE#ҒWkizz,OIհspWg&w.9D5|їȱK=5xaX9caIvW>輁[=d1c=w9m}Ȯ&EFԧ{˛v͉#cpFmi-{r|2Ob 6>~L:Vhֿg;Z֎&t˚>v}мϳ@ h `fJ|`lilrabj~H2 'V8CuݖRc#kfVj(ZdP̬,a` z5/w<[ajo/_^D,okv\hYX:Ec8-k %K;`u= -dӹ/@Qʡ\#&(Ο~y>5I\7V21kgZ˝wU4Az:~:ӊZ sjUjxQVB̹D&vF`tk[6ؿ76Y qЀ=Qlyrzq^Aub}qce5΃9ݕoKyMzL' HoߣfQ;5N3C-*DDžlT@&%dKְQJ[ll@ endstream endobj 935 0 obj << /Length1 1454 /Length2 17306 /Length3 0 /Length 18320 /Filter /FlateDecode >> stream xڜstd-v*N:mFŶm6;ձ1;~wԨ{?k9ڣ6* Pޕ Bhj`/f H8[,fn&&f֯ /?뗯@`Prvp6:8z9[YX0vLl\,fgHޔ jlglef 3|! Er8]@3 ͭ̀Vƶ_fGgGg+?pT* jqU5iQ5q1ꗏ p+uEPw}!9ZJ3 fWK @loU?.n&/Ŀtu2' s.@W_@{ |%U, ,,jS5W؋k\4a ;WW.dp0((/ۗ׿_H,K_%YWGk&sC{q|!7?llhgl5ׯ9ө?Y0$]\_h4ch +W0̀v_*?5ј|1si{s _u00N4_f^39?wu0'4vr5 7}jg;cJ IKILud"a 4Sr5~su{3=PegfV]\_j쿦obªr3q5z/ +?_^k<L LL__ufV_Z@cg}DD<>_ӳrY~k*꫺uonB h `M {KY;sQpY=͈ izAKVR탶 sPvcW<[:Xx1Aѕ(*{}Z ]+8/jrI>l~!uVO|Z .-ޟVOQ}laS|HOr3TCN-8+ FA @k F@_4 !Âh y%aWfCbuFmbV*m JlPIMg5|pfC@Ca.(8Ŕ(H- ҉0m} *- .W8Ԭb<*-{={)Bq4pJQjj+nzt(By|lNjQ̉n@2aIonLZmhd(c")~9Ut b4 DPvZnp"P"($K8gIq>3Oi0 sZƻ1uP CQ=&g!(;4 CuVo$ RBxUo2#d&g"p,vpIArH<&'Y)ͱ`7mGD‰-pf: YV4js:ԿLUFQw 諆'@fF k*G5@$KW(egW, GMԾǨ2}UrbCG1<̅}%@a s؅ XDo^X㒺GLTOXQk0quGVb)̶駠\ B*%3#P3QPs-<<$6NiJLL1h|Mj'JYZS$?ԫ_&Ҟ8Jo[T/ Wsy8xLϔ! ;#gkr% Xx޼9?R {W:BڣWR";dS't;ؐbpf@Gيr֮ңH P"kRA썶zIBXcڜ4v-g7+ͤ:7Ӯ;H|l&UGj;яZ7+EO䂒@ź. @h|X_b5":!wiܥm OojĤ`g`=E y3)j}`ղ۴hN,D%ﻐy ڕVnHu(`::q0 H!b,>WxH4l(0(/ͳ9 { P.\hI⢉p%hh,~"p<#Xi[lЬ.&ÅMyNe1_){ZM:o~U![cǛ2֧\z cl0 m휲r\éG&> A$.ibh-nAbOy4l؂Ps>!=8˥Э6Iɬkg&E[BZM T1Iv5!m7 Wx&V>-; ^|q*Ǒx-41CLhk30g~LYZi|9xzv*j0⏵$=`ls/l ) jJFtN,]:<!G@JzXGq26o-s\cRT4-^d)5 Nת2a׃V`W]=nH_?4E3ƲZXbyrʲ- E@UgOO䯇\ ΄K+R)KL8D֞Oaɺ3vč/|#-3 f = ͆6~79;H&rAa:|Z{&;oK=)79EA\! {VFZwV2?аL1V#F;h"Q`Le\IoX/V_d|^}EߠL'@ mJ62.u2R—b@g]ӱx4^bPvU :u/h:zL+%sԁ_ifroaTCYT|P[M%(r@Z,M$zq%Q`xi)HpzI0ˑįY{qkhn:SC`/K?`/u$ʲ^‘r~'Nb=~L&6D:SQ2iʨ6W(jw?mʍUm;HaJ8tn ;ky.2rYܚT.e}[+Z@.KȜ& {7==1&;̢: pTy(ꢖ5-a&`]ԿiohNndJp<jƈ4rDH|LsrNؙQg㼑]|Wʡ ]^G3ι/xo*:m hs{ b&:AtW`ȡwm~YŠ`s_cz]Ppm%w?N<{~`c:6lSek'HoݘG] b4?a}/ :wp4 yqG< [4pF5WYX3?l*̩xY4Ȍvp4ܻv1rPOl%J_=n1"H&1{O|u JS^ӀAjRf~WMᕘs r;',]?eĕ/dK`S>)zZ&u;ꪐ|#RYYoSGVO6Ib$c!w#Gwn3_Ĥ=3}8m .n~.~ E Ac j~^ jpBAbHg.ݑG f8\0!̲NQ9F,cgB8!^dӲ-bš̯z ]Ģ nh=R~7k^"),B]Jkӭua`v؅re 7`]+L?trcyN/j]q<Az%=sٝ'ЫSt@zZӢhg g(vX WB{$6oRP㩸f|z:)t^S7}`/bShp֪VcXD&G#_}2PQ,?Jwr_u`QҖn%;x "i<EꦏB0: .jQ$zȕfĭf8tpB\-GY%H`\~gֈ:5wՠR3T@,-iS BҪK>hemF(fE0hll\1Ds,[re52e5.zA< "g3|/KHs65e8SNݶ?DHMkܺ]/E!NSF9I*n\`~Zg],ڬp;{,AƷPV' Yy!&kNӼRyGhᵎp$ZRnܛ0Ls,C'v;8t?=Zpgz& Cf(ESQX(xqFi.09KhȳuCI1|Qd\; pؔ"1s/8n5ni ;Ռ^y?!3Md-٬?HԼY6SQׯCv%aG=,r{QzJ# bJ=@Yy\Y/Zܬ@[X)=)DQQ(k`7NyE>FML=Rn̳el;5'"t\pq֨I> .C5uOMQ"jUy{E9! Gp|v'M;HvR؋qDE_YO,Kه~kSʯb7Q~aR|6! :꺜ޅUY4 p4/=Lج !#mE5o\s$DMH|WreUˉ[-011ѧO\v-e~WƳ(ω{ }&B9, |JxFMQ usʏ_>OwwQJ :Ƴ ο^ QѷI\;7d<=:+^Hmdoo0kp/p @/;ȧ)pABgB&L58Ey#E !Y{ EVE`X?"dGL=2k&2-jm85|k0X+ɜtRKO׭*<舩gxGt'\2yfNu|ZMJ~ۿ^{7Tv"Wxd@ojq Yƥkg_O&\f'jJUR쏶=xTX,i9AM#*~`xM$xpL"*6:bQoБ`fO{8]~ ggwVpP9$) Bz Qغ#2,{fiLč_ ̥oejd~ǽ šCc>U!y;F~sW'`z4iȯC+k^ 0GyŔzgROŪpǭ(l5W Qb[r~.ٝ6ôQ cpհ (% l{+0wתM5{4I䨃T_n(gwu d\PamẛnvҀʸzMӷfͯ.jb{ EVvz$#.tzzumj:_"!̜w!]1:!SH~nyݬe?"ٙÜ77ZޥDކ ְ`-xR۶M7r,c7:kT]иWȠm&>m2*>S PA&L {JC{Hnev;3|/Q@[ޱ{@\>ZbK\M]ş[^-w_/fׂMbC4\#gG~(-shUT+$b]o3c:GXG\p oSx *?UC>UP^5핮0qY0d(ֆ| Bɿr{K<[-k_-e2x=(%P[~l2{rv*}Xә*-bx#4't nZiJl 醈\~}V&U$WՃ*^nq[,x:VއoL睯-PjmHIhrImZ!>d`KUmuzfxE3#ZPKc5@qҎ&9׵ھgǜ&:3ȥk`ӚAQjxƚ/֟ЌNL$Of >d K$Μ7^-Ŧڡd^~i?jɈ/@4P>*f{aء{KAXNLFi'J{̅1'%cҰ!u -G*d>辈m(u{A'7\@vбלy#RR׵h]`ri h":.p?w՗M_Q9̨a\Q CNqhB[ܜ}Ï q̏pFH՝uTpyA_;ҍ/nCciLFw f3z4Z :|U#QB7$CF3cZ^ & Xu^W<-,S$ħ_h,׃AȖk-D1W[,uzS'zw:,z4KB' \ u39#ytؔI*9"vHNjB6b3b˒O$L&밤I]x6x1gW5e Pmq{cвұ!b8k/RSꖐj9JNJrI>׉lМc6=4VWe T&"iM>>4L-e!hNڵ#ރ+4Uh3ocDNgN](\vLduc'֊\8.x#?MѮr@o݊SI?%s D䱼 uۧnF /*$B!x/-pJf[~b({uSSe{z|An/㿪IB- ~LIuhueE)s.Q+E{¿Q=Ox<$uS~uf͐.T&%2vRn"AK:xAzCM?nXt[h6?U] ?э^U)YYS^k8C>+E !l[E3Ѩov%[ܨr*&f:/m?doh=k "5ʋ Y,j2^N|;\u.$lPwA[~{aR f+dyFϥdVc&pX&i{dDraqQ6hNhd*eL\~'*ʕnS)Fit#ʛ1b \B`U IsjM'IQ\b1|x)A^h'e$ʺ s>(lhpPDz@oPAh d>toGpgt2+橦mg|s5ǩ!  8BƲ.sbwӲ=!U VSld4mwn,)*Xf˓=͚vf7j '\\X'ruI'$Q`v&z6T$$Jm_eGF3Y&ҰIU=߭W. %a*$A.yeǻ3d<[$fJ4 *-08|%B~vx)W9ZF!S`o֓cg`MÕޟ6](R72!KSsujK,JyI;+NiAIQ ج_qƆ*⏙TQ=:J¾}`4;GQ4v0mUՀ_3hW/CDxP02@`4yѐ!E$u&}0h.SFX7<3~ESSSOLv!P2nCPԠL8Z?iidžK\hi'`G% "faqFG[uU\ɇwshrM 5J™ `[' 0Bs\}f8rkMPV IlZ.XݍrBuబ Af(zTU o- :O]ڶ{H}UO);sב k~_%E܋X)XKڞ}+O|ݼ?ZC*lgp_e `T?;S ;ܖ9\9bcl6c 5XGwvFЉy4Vov)M7E(]Pvκ{^p(PJ=W0s*C81Xm /{\ބ%!ܫpZ,!v<y Qg߾ ~}@Ȉv'"(Ω#jw-<>T bJbM<6V(T'ˑe):\uK҈fzJ7ր*'C ^EkΙ\b>[;}n5 =o֍,inܠ MK(m 7Odf ]~Y4Zل {f ە?ٕlhQtfpdYۑ+x0 oz l(hDE鼜{x>yeq<{vf*@ǂrKlrԝ"pVJoSdBAK5I|$Y 4'Ɏ:4+:WHr6fl!-d⦐f/V ĩA,qVZ):Gg 07Ѭg#3F%<=-l19ŜV>'hr1>*P83 1z <|_!u07M#p{ϞK4Ȭ[_-ԁ0S;y-]|qr ٪/=v0(Qn8xdq-< lD T]ߙ'Pa87&/g[b֐S'!B!#|m8j*h; *+S8O &'AhQܸlq!fHbA^pt\}jDVnQcoY &oTퟞƮЬ?9`"EI^2Li4Ď{prȘϘ)*$} #2*?Q$ wԿAa#w t5b UU?3fu@iy`Ĵ;~~Ѻ-94%kS- 䰳5Mʖf`0ۂHe}웗BUu0Z U6dVњ 5P@$zZقBjvV`= ."iK1WSFGmPa|D"x*e.@7rSh1,Ј۹# X:] "W,{?rF|pch$^N,;-6E)bnDj\R(8oʭ=Qh'Xt3{e?;Mv>G6Ǭ eqn6~w IDAOb{&p_$GH&_]5`(DX(-#KEIֳ /y,E *?)B!j~{D#g>5V fr/jN -UCrPaB⤃ޯ\^Q&]Kx۪~V!-ؾqԭ;T/[#<|Ij:b"i4$Trc8?pIò~sUH+~A慇AݽJ@xc&4bEƭMdv6+!ħNC"'z5mm S~1gMA6.OAyd*Ӄf!%xL R;Mvjw"ShT>MAuHK wǪ7wo z QQ&5SxKI $Qf RU5PO3B$:,<-<юhBP,=D9Nb7CJ/~A̒'|ģCwRSM~eq,n@}NSIb`t'9*&/nJ[DӺQ>=7eͨ}n)WN;?k 3IAw˓0y61@QGAlԢK`ꘀ-]⊬j~fD*I7R d&Tk9$-E~39u)Ad4aamR4F X֣:3%9ş*fHp(o k(z )ZK+|U|*E><{]0xKtZ7WZRoPk[ey-ZdZ$B n  4h1WXl^w{quc&VSkJHX\5J0V1ESwُ *[sɒfNqINr NA%qxN=]z'%{hhatgt 'aCˇ OG}Ua nk`o%Fo;Ѭg-9(;-U{®Z 4:ߓՏJ{VViA [A(w'=^C\{kx?(UdhG('y"n]%7pQDk>)i<ʎ#=[f45fTh'U36),C7IB 2D=ݼ2>5{]օF{hp$I9-IZYD3''-ݳ#Y,RCK-lGEq>zk'%Rk帳уM ~&J K)G/uh]8@w#I2_:ͧE jq0zRwD#x\ #l%&hſ'tNJzaN%I_*`$HLF?iR z7aklQj"5oDkN&D$䦊/Yo* Rxe?Ǫ_ohb6Jy9@ױIjãL¿;mLd=":Ǘ EvU7QWԻ =G.bEgF Edݝ%I4iI1e6Abfha: <ܐs(Y+ϖjy@]w2e瞕?n$ږƂo/* U{,L;K`l4шY2U]:"40ғ/J3xY<NJ)RDfc!F-sZ%YSsȵ++D &O̞ TF|R&GU\.Z%ֻw0^fx<>B|)k :Ϻ=Y ټѾ6Ꜥ۱8Ci^\*0\k2;"d1NI^q@.Eো$3' {KOն6LA[i'Wq%,x۠mE@HZ vU2Ƣކ ^dm=Nzr=O5/D:H H{Mϳd!|Elf ٟbff1^8!Z6o4]=I/r۲q샩ey4ʲK6hL*]Nz ٛ?SgdIHFVmUMQx=l$Y#1N=p&`p"QʛW_*˚CK8P&\mz;b^}RB Wz๓apNCd`;ypb-p%ڒ>ХhEp߷詈?BMUEkֺܘ^D ~/”l+{v_>$ CE|h&iKI<'GQmf\hp*lE9.z:˴+4?B(o Oy+$╬څdx> stream xڝweXo- Cww H НJ#!H4"HIH#! %% %RJ={{>|k5l-T C񃀂(QP) @RR aIt@ Ds&P`; n2{F0'  n'D#)"!(B `N( vEcC; #|(?pu'Fzz&#Uc#MeU1: @Q`B+A@C@`:TavpmHbUI  @ IapBy"uZmn-#hP^UG_'ry jl i1,. YA o/7b$FbnԻ.)lk$. \4m%UJzs[?~mAkdd$bwzU3xx`=Kb >˸/W1s^ĭpI,W nܻ%ݾ,%XzNsf/(=ڲ~u{1@waڐ :Ὑs0"p&S<ɉs٨wQ`05Rp/I> <77>t i:8'|엏aQ.Ac> WiF^\.$enhߩ/YKok点ܿe3;j]lCkJGj !X>E1bB\묵 NFf r3RNLLu F(]r]Fie\n4c<}u!'9if~Y{^'0ِKnSC艔ajF6mU>(E!^y }|OH!vɶ IĬ+3$iC Xg#*7ߏC@z)ԁGsT +>wh'Z7\vzdM7t9]I[ =Q 0kVRRdr£dVee2$\>FAǐK[[,j 8wx!4T5&ły"rF+>`pX}zajRL!ye : I2 γ9v%!cec4^//fwFyN!ά>#=xUbFn9"UXzhL 8/yw-DdiDyŮeR`Z.̪^w1^yҋO3Z;p8hE_V pTjJKH*_lDzqm |5| sJ\;s.J` in7y >^;X֓{TX5I-&.XGB Sftt- }^Wݺ{p`00=Ig"eS1_ 5s3f?p#h($iU4^g=9ς3gk'~ r+4Ԕ.?z!;}8sV0w+b&trx/7l9}ƜBէXo9srڞIg`2 n={%Hz>>Xm3WJw@h:,>Wn:a`C7%IQwP{VSCW ƖZa.&\K3KoD% "$JWVdwN`LJ2NpNZ:ʱN-o,{(SRKO[rWTMin082pGl2LsOL&`Gy-f-Z5t/.6+xO_Ḭ沰_J6}ftLke5dی=MbxwganZb1VҖKmt2T2V` 9m͍Z@#ȻVTТ!Lj-JDcP8))~g~󷶼D0ôA}DRQ3>Ym!0EDқ.bSھhZ{+,,W:tMu}uT{Lh|< М+Zg٭Jt+uwh\w.D2I'b+yx֦$x.}XYA : C%{ / 2dܵS=lދ3 4g{&S UN+B,ޑ|WV+.h>-OH潖3}"`=Ql[Y">MMeˑ@ܘKS:p˞ZfI iZi{KŅ* s;q˻  tU_ݺ. )? {Jq sjŴܲ`]mW"Tw2$ xbdAJBR/İ!ŗ5*^ fu]E~1dؐ ٱrn>p\Ay8ռiDEuY(n?ASNcW{erΩ/i1Shf/WNnV8KjsO`1pB&S 鰇/ l ߋxMDEpwfob+pri)%obTήI'Ěsfݷ4Ŧd ]٫/hÿtb# jldhk|@k+;(i%OJȂmDݛht4]LBk9q6B[-gCLiI썞^ȟ[s5׿v3&h>?|PSu:ۆV`adޞ&%Q,^eMp矛3seJ`ini8W`h>! VwD(x=9fՃY;;>vb:(HW|7 Zt?,xYEèxm6JRJU9g`7zt)qJwF-!N4uK0?&u7%'"cQi]),;\UCtO&fV`u:S&RN:ԟԌ? ЦWc^3HkG׋yi 6DzZ_5`QkSKh>&)MnUz,ϳBOoK) L@u-&-fVl$il{Ecn@nbEMyVjb!)yv` .58caZQ,[<.b2(+|GSKD(tQ H3bJE ٻEfqw.ط3%rȄ!)87QtA9ֱKwKW6*|]!SδB<ƝOATYo;UU+2Ce}ܻNَ + xX:~%w[{[2r kGW/@w#R,!gCvu/y jۯdu 4/Ƨ]:[?a*cjT%Tɞ~QS]Y7<=tYL+ù.$^& hSTYG>A~Da@NAء㕙;2\GIw6ʗ6_jw@.,1w~dR̬WijsdsmSD6ZP3֥;.l'CM9ݙ`~ ZZK0P2#}RxqUzt'eqodžn=lJb1AAZ"օti~Wwxi~kWH?W :z56Dd~R^&?zdHqYeky$4j,T}ͪu6ځwҒy8lW?dc Q纝Mzw~/_\TQk?sFdEIm$3. Өt[W̜d'Dg^e] s=cnuӊؼcʻ1m>ژ[%cRf@SJbB#zx찐ƛE\$zAnN,[e;) k[XUUy10wu2t eHŕ]gEpG#Ӫe ̭4+h\W]9G".(i|9gv}\ utz]R7^1ˆvo} ι|eGs7i(64|MQKm_wj/ KBXn?\m*bxKj|tgf+>"YOۂiy^*#mzܸ O5[t!/yrEU~qZ-1Y9kЇ .]})j9ƭȨP2*V_ͯ$ `W(voto^M|,gk?DyX^3Rlԧ髿UGCph00&4Bދa?f=ʷf.Q9X~HxL^'+V iRfpkK/EI*g1-Y(,4k=$"m}4)dcG%~3׼s웇MT[?;v4"7CI<;hSٽr Uz0j[ 9[m!R͉enI/K)i7s>lV tSܐd@ל! LdQ$:)|l /nqB^M@X]odWfi[8 zI!Rue"*b Rk^ߞs71?ΡemcU@% 87{ !h7ֵ`|2+3RGOrvkeJ'54##%/\ÕHĸNd9-z SywM⚉w(^D5j[zb~Njg=m4枍[-Q(sˠ3%Y|qՔs~:gs־-xV ]] ļ:t[yyr VKK 2vYCʛȇ+4;#_75Z|R, OhlHMN=NN9^QcEŨ 1Ƣ 8(aBPJNq} ,/M/@W#>;8Cc^NՏ%2~ K](Aaso. =,argrwKx ;7R㲬17MN6sXÆJPkM'#Ac<#˴򹺒ġTJ5?L?Pe=Wo-瑘NZHKi0^,7j"0Rp?BrMԠIHxΓ^Qn?`D'L4].>ǦzBifqvuF;m#{ņYVF.4tE椵>>x@}5败puCU'w!4U wEk >T|j+h35RF%nk_ ^ο$q'kIA%9m0V㷺xuPMLg[0ƺgj^I yz[7. 8kc+ "| endstream endobj 939 0 obj << /Length1 1468 /Length2 10056 /Length3 0 /Length 11061 /Filter /FlateDecode >> stream xڝeT[m- ] (P Hp+.)R݊;(R Bqi#ywd$cg5KشTjf +3; *-3 vH]Ag0@``^C`WW=@`9;X9vIG/g nfv`k`0$f` +@Y$ngpA, `  b[ W_mM@CZSKC^RKZ !/+ Ѳ\,]= +T%5B/ݡb"Y9ځ 9AQ]AYw3* M*l'  ` CBAh SQF\7gs@@/&hxa 3>G˟ RR]ܠ^9HG(= /9E~, 4wupfBܠMpO5/`Ȁ]\P_3```3 B mvq9C % agv3;ϜC,C&hCg@ dʪ mq77˿eTP:CU]v=og]_*@[!XAZE P[,vI{ 9ہ! 5afg  iVYy5 H_BqS!^lOWB`͟h!`t tBpx3sp98yeO(s7gghGT[bq$ $ -I#T A3~F˓0b\H Umd01bU]YwR Fr߰ +Ư< Qr)`CrZKD\}w-lGQio;Dkla@*rCK+s_ )e`M iYgdBQeUoWx לj]ˣp?hkV-*ä}ep2s_EOU&"a׳u,#HzA/KoiP jlwqx0_a%h[eZ-oعߕHgp׉)4e׈zL,&Wxz2ȣ4N#ehSMi~w\A8v"TGXnޥE," Ni4F|1')A@D PI,g֓;6̕dǁƐh:? ~ytd֝OZDd C>l6{lIGZɃS\?:֥Ria%s5{Y{B?]#]ݤ 1aU=(YԝUm22H ra[ùum&hZJB"EZ!80R&n0SuykPҪ.._1loqcUS$30;1-Ͷvo^@Pk栘VݲrŨa.\,ǶiUE)W ]!$$)Q-=}T%mv!!MZjC RL8u!:+c`#LZ~Sݿfg^XޮG.Zè~U(觯mv+luՓ17ǃsl1o: x5Rp 'mg_`ހR<%DR(:#¥{_~w0rXF~\>B6 H*ڲvJ I5Jr?6g=aav|-MK@T7=I?*R%x6 !r¢{diJ/XrYB^eЭxA$b= pEzcl^)Y' 7-"RաM7d]z2ڌ.0q= cT&K:Jb #f%Y\ƀI3E8Gw. MKr@ v.EvjZr=+RO\xvbD0(}9ӆVu8!ws;¦~Gt'nH> wԛʢ珆/&v/P?Up9lpWmnc讏L厭:["27Lk%NȄ]'Za ;]7p]t`l#⧀DidӒ 58٪5/ŴJ>j6n x7=ў6LR #7>|%3l0jn&+g}HNDv~IirM9o1֋@[03q]xğenZş`DrzA5k 8!c7|G*Q+NxjhiDg rjA-m%j]sIZB/uO@ų,΄ymځNm8Aćd|KTfu"%e_.o乶ue]6-?]JU'P۠j687ycџ"ĈԘIMQDqܹe)YzN!p zg7IDVaqB|rb@O2> %ђoRs~x@c [}ʹeoWj&8WL*N#ɔGmeBoH.<=qVe@^~o]tt$OWCcT;K7sA=Fb?^f"kpT1L__:~M)3sekL/RsveZ5eH w`&?Ҏ9GN])b8}I+DwL Ejc.sٱIyuOqdEʬfR~dݡ6_C/ 1 WZ9W.l]<>7|Dzi.'j`Fi{m@g>PP+ úTDl6!n8;PEB%JcD혲\ [Qs3Ca0;͖Y6,0VjEX"-3.ҌoiZ嫔rbKsmÙf ,'G7fh@٭r)yizz Ԡ,6^>aYj\Щo1_y@\ nZW8 `~~ͳXŸ$7AF!~ʖ[>LW@nSomvːL %÷s*^?zdy1v `0pDs;Og`0{0?;ϐllo E!7a eh;bv̙f`"T}vöŔo se3 zXY*MS4Z0~̖BxZ6J'Eю =ZEKcةkaL<9L6݌cZ8åJ3SNXh`s9t{#g"e "-~%)|7vhlWcAs$b5DyT>Hnc}rK]vIœr,<+],6+$YgmX c>17n5Ĥ0~!Tdƅhy^۪._D 3Mҝkr=+2 Mmm\ |ށreXHH9U 5Y>k)ziZ:6QvT%4%CX~*bqqd>{|7)MёBE Yt$e?ad5 7״^`%i>9U/ƌr#gPfY |hԮ/ K2՛ې-h/!1Z[WRu!@z|Ӻ*Wo~> 楀I\9b! h=0#e;"ܸ܃ .}刾 }W&YLyIIFWʞE9,8HD9@eW; - 0@ZupS|<$zo?D!g5 !Q&1kM ?|HZawQ++0y2oYl=7lC4O2v'uG ^9|s*8|Jh6D_XQ όJ%0Hjއq/TRI i0qڳKcdxUkWhimx/HY?BEˡvϫ:  1Nh!)3h#z'lФT"C^e-3PVulenB.GmƼ{GKٯ_FXGOvy#pҏ4DpI>LbNyNĘ \D-.v7]Fi3]Ɗ;k ͟L(: >yy6pE$4N,vz8|qp~){*;{gMBi _,lupE_~,Ҩ!7dF+4I GYRvբD́8eg9fC`ZqvGI0M$J?/83#5{n>ICs8fټ$t^@ymZJצteNΙALKoq%J7 .b]/Tv+3X %{w& w>1 7~7] `?PcJ ]G1;ʇ+[^pEO;X\AQPW:z~Ńbl7dbMe5; °p+*0fa5̔]ʇrvqF*c i t#y+U<{UM"5>IzOo%^U/RЖ69,&ĸāsf57p$qۛoƨ/aaUٽw *1`Bx }u_Wȟv}aWzv9{ƒ*n> 1=o~hu60L%wN}ɃښȎ$ڛduDltCؼ7:V/ߴ5h'_[@f gd쬛YX[sv~x%=}hugbiM{J%z3LI B-о'ܡ" فY[@&_}W*z@GϟjRNuXڍwEBW[~o)n-/51?JNaq"k5đ1)4ӽM]Ie-VhMKhA}q("#v4 ދ)Aei-S+Gkd)oW c"d<ׇ \X( H3lo2TC1lr SuJbb.Wi:{1|̞-:D5|j'_q+wغSqt`8b \߬UыXjv6*Xi]2Ol9 ?<)o<ޘ拢D Cv*6Ih 02 }%㆟onӉTtNZ:&H<,CenuBĴRW|M,n!w~B\A wN Yhro}ͤ[FmGvalԩJ`,p`[CAR!O`͊dC<uyNg/NDzyO[. qQLbsEWi$gqA&J#TeY&nhwm_\NxF{E;_ )'f5 |U,ߥdcg}1M6։~AJIa޽Cq+2 lZ3D_˭QI?CBg w+){J;<֌rͧ.XjyGFn"a;gHNf cV5$XaWq(VKr\n,rV3k|Z)W<Hd\\{7rpX}A["džL}9%V.trScpY`KXWgRXX>vAE-n"ي+W`頕.-*6|8)ث>'݈<גB *gG:Kǽϥ1x\4"꧎ٺjhrL좌kG^yOH0QpHSQ6 WghZyAl!׉#9iXrRi~ϻʇO"ִU+ Oi?zְ57Fx1"MQn%!eo`̛;R>&SFW~F'R+kn aӿD.W&ޛjdA_XO3 {p=PS 8= -Q~8sѮ j9w>GSMpW8/6I0b${a{- xOu0"u h)UB~CQQ댷D0tփ"B~|2e_\tmY(O+ҁ>/TqJ}7XG7pFf' ",SϐR]5~v ЮI"GisCT]Ζr.\%Ux=X,*C9۲4u m+:c爦"0<Mkz4t3R7rhwc[j[x I:X6 Smú6<r7_< %xyȋ:Gp##HJM?~]R3R\v C1T]:}.;_W쮴Vc8 -aL=lʆ. +4 ߪSo="O*|NfO &ZyJJGb6R] _Hz̎-b%?(xwS iػdO\:DFhh0w"mJ0UU EV]].@\n̾?8<[LbdRǁ{Z*CHuTsZӴ>xOr[aJ㘘c$w;:ڃ?ר) y< (ܠ1Z[Ŏ׾lv%}; 56Gx͹o+M1)^Жꔅl9;1n%SF-k6 )2? oJ9RTOkoeyl[a`F~i](O΅b4=K/qXS=k[J9D<ڸȱ^ MZJD-Q{Pл !+B=YZ̆T{7 =)9uJQ|n Wߦn*rj}N7oD垸RA9x+ǯrjjQ|YɚW;:j}=dǿ:gt@7R_2o"r'8Zf{DT}Dkِ7Kœ,. ISiq/>Keay&cs#,~mBqItqIgJB𪃾g0ϰI BsHXSGC4FRQwoF+mo$ z3gOZQA =6Szթm`ۄnpw@lsEm&gX9`/ɧ5*Dp1cRKc&29č-jTxަIX4]_?74)UL~ۺ{``lU%Q"hKS>=ކOvQ(S&4]~Te$l3(:^2`HK/C22e 6^N9붲g ꛣ u}81[6`jv 'Uɜf$%h-2ݞpwI #d|1LBӳ&~T[tZZ'x+$LFAy'מ"9M28xѰsdUsK,eKD2!狒Y?A_z _}gF~+;CP%w%Oh.O;pXnͬhlqs5@}L-iz<',M7NG>a܋N<'0$lHŖ^ &Ovt^=g,Mxg{[$rv~=Ĕ.k!=W?Q"IHU]:yVV_+VWFSދ$Vgyj]ypybջ`oA6w9e%'FO48!rigˎZ7{L_?ibM@Ji߫>Ȉ9^̈=|mqT;Ge绺Aۄmo-7+xj35Ϙt}SJkx/G]mf\nMN̐YD_O+rO-WoJceE}fEms(ejձ.wq.cC,ޣ(j ^)} 6ĴB+7 j(⊅]}:~Ci5lZOR/oFV뭓nKO'H:?;Y }];.M?O1!RЏd՝ L"rA| }IlI:RigEQĖ/ZE'R\B²B؁` {#Jq`:lQ3ch&>/Pztg^Z36A3:W?0sN = sDBmk5:myOڮ]k՟_)qNנRX27[5O"F1\n|V|iU> stream xڴxeT\[-NSH w ]'h A#ݣQ\מkq 9Pf`e(*i\9Y-H44.@3#H m*7?';; @)-^% L 7 :Y\@-"bkmO?y3 ;GW;[ Ϫ PvxAs hiHkdUT5Xk999_-Z2I1eM)P Wzߚ۟58@W?i6ڷ.z0؉ÃbdW}6G;h1n ˷vmgG@+?o|szU[#b G3׿|UUf 0dx3\޾@KHɡO˿tqǷy\֛\#@=OLILYNZJCEx %ǷX࿬TgT d)V+ҟIھ 9z|Khe sK7'6-PNLDHYva/s5 `ef ]|\܁DHK[ r +G?oSO׈2ͧ# ` BbSvQτW.i7{{e3 l,t Ҷ@KU[?zb k{~%3Cod};plWw{㡅 x ց*I)j2'WY8Zڂ<f..f^HopCl G rtAxlbD@lB\66#N_r[?%6![r: r\7 //Us5/na P7%39o34ӿy;zpcp8xq87N9o@'iᗣ@致 JX>֣j ">"M~F$IW0q C,g3W#7f&eb7Ӟ*aBv#MjW]T1NJ647FSP킍҈_ڨϫʧ`t{b<09׏ߝEy[7Vu Anl]GC3g mf w wşD^Fk锴-.h{9vXl΂ fK{eg6K4vf';S{BpXP^'SK]"l;XF!_X8jp[-۠{Q;U%Y#Ep^ i۔ W7LF"ʮSvŎXUta_J{+nQS(Ǜ7,ٷ^e$-wԓ fB_BvTx9J.I 4`j%묭cL (cZV*[^FtmfbG w[.vK{NT,~љY[e|I~!Qw=|͓1%oZ igb_o4d$\SaѮ̪缧=MwJ0eu8B~?a)qHyI"dB[xZ~]Ω³yE0zdMCV&69\x?C}N);aJ dcu,ml.4Y)5 Ix}Eemy)x9k~ CvGR/C1bE\͕,?fT׵ ݗ>bJ%g;kv˃hi|ћ_ G3 ΓА|-:g*F:*N$ h`HT.=> Kz{ѦXugg4ר2G w))[Bc:"Q?24Utza{Z "ïY&0C+?ُQl8زwk83M5OKFYZ Lq=)Ts%dTAyiO?&nf>>9Y=t>)ZZ:֫|N#4dҹve+جѭ b4cVsĒߪo+"T0B\>]lYCK_Ii>791WqHv؃>~l+4{nӀ.covW/a4JƵ$aB `G"ܗ DOT诊^~{T;>іBұyFA=\ }3)EMUܚfXFCt!Z}/ tvEM?˗JoEo;o\v.XZ;7E?E ,!5j=788h *+%u^Ԧphccv)Ravo#0#ךy?ewq`pm (^ܤ'|`Ћ`,qP:D"np?2.Jbs#N'-V,dO?gmMux|g6tF06:U[\~t5lhH࣌,- =.M:nIXȂ#`Y#[2mAW/}^o{99pZ2U.\|L=ށw-5aYT+K(HL;XzFڄޜW#;9;/~Vˡ[ |9Dl 1jQah#|گ͘/:16Autr+ !ŗ5C]?=y6i4uw^#nA֜P5'jKW?|vfk&9T-dyw.E;.qN"ًx_6&RH@MsAXXf)7EK|'/:#{z0y61Ir}$-Pr_>|Uoc5nti$uxr|kP әc Ƣf58.yu |,jZCԦv`%ybf& nuSh3&ΔE".~QƂЄ[\_x؍EbT?:Y֭%TO'Ql02};8}Guv ^lcKz@v@fRư?xd)&evk-sA;,m ğxLՇv=Zz{s /c:L6"${].7)-'Cy5-oK Eܟ8<|#]!f2!:QFbS0ZGűFg+Y|yTQT ϥbIBqZ̘P.@. &?i;;t3ռK)ܨq湗kC(D5In#lj_Jqr%q*Ev2۬T21)"7WZ1%NΗ+{-_Ʌ{s?Quqب}՟D`|91$\EVQ*> ,=*;Lyq1=8 _&בW_'վg$B.%2u8lVҚw3bG= }xDie+(,8DJ4 }x}zu*?u we}<BzNw"YzjM:=m 8,)@_ͣvB݌ȫpAw3zPۛL|R@=(_HN&t_cÖS ~wG]İwU_r ziN~^AhoT10p6X0#4wkj7Ǻ~[FǡF4co3)FhXr@'*+lgَ !fq4.?ze mҎ +nef%eGhGB_^x.stIMd}F~^<S TًiW=q;˅rsTR. 5feFȗc 1C_hNqX[)1LZ#.gjDD%G9!lWkTS{[fQS$_O_ a \i+r^v8)X&h,B;6*y<욱+Ф^EG @ Z&ڢN^蔰IgՁBp`h_<8N{LlcќWpqks :q9K^,Θ$(`0B: dF`㴂~nG+N+ȓF65 CA 9,qe FR%r|aQn?b$L' J@[1q:h=cbKW ˖%Ț%lHK/\'x~Ǹ:U4ò ]>C6Kn3%!dQ?t2U"76Ob Ϩ~ЦZ|<)(AQϷE K+icI knm$2\2iH -z$bRjvOƯ)Qs[8=e?JRjW}]7ngl .Hԧ0n8~dyoxQHpkˆB N]}B+X& BDҢ'ũ3,d z>6/xGb_-Zm%k1@~ga'qiCE94,1پR܂'e?S.a(\u(v^n[[[ԯEhHR6֥,u#1)D~ |d^T Ef+r, w50g>f^4]&jj_d2(."58zhFP% ߿b]WqMQc밵)(Ţ9tUk1"$R q^i0UD1-hE=CqnxG60B7s<я>F3b&!R&|qGOd,L>Tv!'kDHב 3xӘ3ߚlD[uU&)w~|:BOCjXo=c]GDT9ϖ9UbsGwՉ# E )_7E1د \#&F *4f }r1$%1xa `OWwV6wM}/Dۮ LH~;Ki"Q1ȡ׹؋E1njٌ( õo%Œ|q)k&a,A?+R[P@R)p(*{V^(.3gnk\?M]8_*^G^jδ7:ƭ gC?Igo$BjΌ"E 2P<7+gAi1B#^hj'hQI؇HAg79J?Tq;Φ$4FuC+XJ.Uϝqi)\\eG YRCw9wAkT">zR)0Փnn1-H_r[ML2QMHLf{:9G &Ism\ED`6l(/wg ]&'Cཫ[E 8"Wb|$v3!>}'=tD?ոpWG8v+Ou|y2FAbtU$X/[H07vWq4Z DAmɼ~vT{HFÄ[ %΢dC!bvC{e VWz]Thp0]0?]AI膆=ĩ/Eqe=2VF #|ٚ1G=e2p=a7|TD(p.&R 2Ʊ Bթ`, ?) -aoΡ+{ 6kY4L0mo h֯桁Ō }h.O-#V\XzPIRg{Sb,5E%';ބgwU6ȍ.xkG"/ha` "+Ώ:ę>{l(i'V|XR#1^K|JHN!VͺOλLa`f rmȳ0>^dN4WV*&P}-vhS;C02Zw>K=u L.9C3)EEpꨎ$ٸ!&.D&E$`)\MWC6H+n9f)} >ia@OP7O6%^sUvmDHm1mz],ԱħEO^.l=YP[ dzj Lo E(,e3~?&ǺgUbK٬4x2iG-O#muIFFrga;T}2i+8F|B $}=$4=AEUz垥ʉ" yMܺDH,Bc Ɋ?w60M;OaPZq>G sB =zC5 Jnl/o'tVCω(=Cvrp b-L,=Sq|a@CU/#[xܯ饅I-d#ݡ^v3\s"7W=iO^ك|F0P&m3yw8;~H3=|cTM(" fS; oL".*˖MY JFRsn*jKdK*Yva@29 )E+jgXv>,*-#Ӊt{.Ffjﻶ.¬L:9ƬQGt5e sq!nׄr2Fg~4l0Oy LB} 5'A*뭩Pؙ`h챆Д2#s75VRRhu8~Ώ֬(&Vrj0i}gA`h9$$^tM3m@)zj(?tԶ-~9CkB:w#rS.δd&B/4TQ`\/Ϝw$J<|DBYuV| &+xfp%>*_b`}AT9ɛ&u3vD(FyFjc0|4Y/6I| 6^WvmSbz b>8-bJ  M KgXRk6ĪzieSRûÜh9*\M}~#n6ѻ!lףӳ+)}orz9\nt /q%,&>}IX7Lc8Gc xI.qQĒ:dLO$M79"Ǚ5{1C^ޞ>NcA֟K;8p9(䅤HQ[Ƹ8#*2殾}X&GF%v#{AMA)bD5rakT6q! :FqN-wB_nG;KcxK?p0# ޅ N2IަEh kC"đ$Kuޢڂ=8i)Ve* dMeOѪ'FѕW'1ԇ^,JyvB^ij<+*.[a K9bBpU1cvL;k1_NU^Ks@E| E )`sL<yDd+'}S/||;Hadgl\w^(0tzLM:/M>ZApJ-V'ob\"h"ꂶ6{$4 T^ Tv}i,+C5З5z|-#aJٸs'jJɪL'j96L;;z9JԄ7 !\1G|3) twC d6su~myLG ˯<5ts-'!HJ]GC+EVD'괐Yc}t7$<ߏnSt!$ [#`oŴ7΢ !,}yp.gSy/yޘݤ>竳 GlF'iG[$fc7`2tb' 61>'ɩ<~~ˤYƖ`zoJ*S&%Rkvi`IL&=tA}wR&f^WTbnvR@^ZDꙞ1мn ^~$T'А%矾SKJN|Av'fAT-H|8印7p FxvV`qIgr.%NF"J" ,'ԷdGXAA;ղe)7IM֒Sn?tQ0zI1x` o饶L i2"<͹NIj%YOL}?wy8[Pkt _cvmi- nu4B vޞOW ?nr+XVuD8A{JblBfn@IiG{j3bH81Dfg?^(3PpĔZfX'f~Ju $ɿ:k5H_=ov9J¯WFo嫙4̐:EsR 3OލnE-)ɦnT8i.cρnd}C&^`ƒ>)sSL+`r~Bi#yh;+2Wl_a+pdi~TE]Z)"lG`]_Gέ}Z 2B Y-\HΓ\K־LE:&,-`˨:WN\(vXvk;{Cj;ݥ3R毶* M Mg,EDмFKԑkWeG:p%(hjc#g-T_!<- GC$:&jjՈRW,5>CpV Q=wv[87ӛ{H?~͝ܒRr!?k9(f=.qGЅ~0Wt싦+&Ea4t>C\[,ϊbKFIA;m#(O  c:)>nh]1. qŮH$ SqՅanԡA)ȱCMG%Lg}r_ Z[B3!.GlWAU+92٧colyLB7sjw4 dps'k8*+ש1W?@|Ve>[$&ۍq\i١o+1V?|ͺC(ѣ ƶxҋRuV_*ZQR@\KJ8e~-UD!1auB343<{ښ9}gQ4 +Kuepۗ]L~GYtbxzk+9.\̴-d;2rLUx>!8UomW=N'?*Hх+\%d_saM+޺wS#Y'y1Y!nhWiص?zc9ݼ=Ū0J>ݟmRFVTnH"^3rDɻriSpdy{p5'2i*>:y{ v+X(^mcz0c 2<[)(icK5{ϡMlAj!B)fFCA :HwwFwÙ֛lGv`zG&:@ǎ,jYx3f/ "aձʭm 5^ןĪwL]9x/|Vqgn\ | C{"z4I=ZoeK4%3#{` 󁥧LઽJH9Qq*fp˵5(܉ T8L֦& 46ϻ,ʪ_L/8x6;렰kz˯ĺdKCV,F1Ih@oJ#)B\w;d_sH?h yuk֏F7jEjnI!O A_/ڻ?}bv6I&:-FI3±H1kU)n`4]Jjǘ:5#YgrK1*v@NfFk*e^?%*69kĆU@7PWa˒JN3J i|nψv~=~v}]ɹ!'K>A;g$ݠǎ>&o;tHN*UwX!%e<ªl+'2LiFfVb}'{#2z I(ۂL{NNi>bQQӳ,}Px|ɣDc6U 8Lso=z&W̽J.Xdqtʟ}c]['5pߙDHI? Ҥ2{ m=Y!55|KM?1#~ɧ?IϒmWB.}5-PNtʘ؅ 2bŬhqXXD9 g]ȝ@qYj&m(b&ŎReA@4Z ,ߐz~N#fGF= ĩ'&b+ym'u+c #Ge&^8c>婔UY4TWZ:džU8OsP ;yߘ L!iS4*io3F4.o;;~B H~kG{1KշEXl}E$&=yԩ;F>l"MA/:gKRSj Jѫ(B^> 'o1B:rh--qd%iJ %C(rhfs^w*1D3)~}E>*/I?B l< QX*ZӬ55R0D&ءߪ# 4̻ƥ@<}Qd5&j_J={{u@$D_ULIo *t=xe9hg螽_,_鳐q$볲+=a6V i`7, XBhC?f{6bTD2=W[~캖G9MB6ppII@t&76C EY} -?W:ۮ)K$`pJ,T >7k7`Ē@J $1fXrND?qNMň#YCg_t3(4`0YB 6U?~ɂ'A3\&[]$lxQ91ٛBksൗ`0qVPWτUVan'Ѥ^is`$eA ceXRmFwv߮!Ln۠FH+FBVLI੍dʬcN[m$̯J_RIK։,|k^;sWq7-l=I? buM]Bvc#rx/c =GnKx,W%gSF(v|W-B]?iȔw-^'$o9r*݊oUq^ɲ椹pTdg&W +,ܓvp9VZm]yhKG\]!8UPl|F+MW6W8 :18'h)o,eÉRSԞP?{Sk}!mMT9F9L;xnL&W9ύ2vNtsum)ZĒTĠp<1D86a#%rXBvA] BB;Ǭv4+|q,Sm[N s3y^00_DLFFӣ _[.W)ԝVUJ' {\ Ylɝ:?FCR,?V# G#jXdmc C9JRC6Eƶ$ɳ-2I? "t 8ȕw?tܖ1<``WK iV~gT;9ݰ幒Լ]0̡OT9t =c9O5\tr3~ D![a4~OSS>M'C.u:NKk a 30U# A x$t qFN,g"L^pD(>~Z:(q2%#egHѴE2xMhz8 wZq;³\EuY%zN`X/J-t XF-C y 2 \vcE y )uyMK@OnTo28^kip7F`8D>Y98)tnoVB%StY8ߖڿ+fJJ5fmV˷y/A&('Su`5a9H >I nS?g+[ZQF<ddDUdgR21ON2S4dYsgdҾo!"s^^gzJ5goe>t) !J>Mmјr{.\+7B&[]UoQMWZ9Wax XlH33I^؇WP _}2Re Dx;;BM$:~gs#c%^uN#jӪ<9T YP ڬ]ǀ*湬Bjdgvn`z1&&B3̏4|-c~ q{ïW>x(A ;/XhXd/ m̒J*݆,#E$| 9Z ΃e0 W%;g=2ub΀LMI(i vmQ41DS/_%mdiGcxy˟IhW U{I]CQukM~#GqZ(i^rK<.;¨az/r={_EXbgR )*pfQMqqs ܑN.]BMS-v)!lB#Qj5̚|q.JEzDȓgyw/ya8yK-l LiJeݥ?DW5׿<0L/)*3HEej,`$84ZIqvknZU˞Ge. V{Zlͩ{FS޷*/zuG1LGPo@m[ vC9^4A=<3m,9%72UͧwYB p;Ƌd[Oc'G˹p=*ȱ?koP峏4حe;+hU~r_ Ԋ5.`d$l;[1քoLAp#2 U=%aL=_k9+lQH*ES 0H"͌ysa|= d jzmf!ty+h] Wkğd0cyvnjD_@CHi"eBu}mApWkvae2#D]Q_.➽lz'b+3nr9~2<5B[| w2| R顜I@-)n;#tx8EaIKjTv[,VR R[ PDjXGh)#1yaϣaI/-m_YSrpT נ0 q$IwSMFog8ft[x+9v tKCkrޛp!Dp_<^jV=cfgg,VS{ZTBP27?M]ѥji>ZJɽCf7* td[F|x۾[>mgW~4q+iA2΂G @#G'7^[ pgWaEiS]E[.*,I;\T$V`t_d?"~'8V:Q39ǪH9Cg v+1 ]pLs#YwN0?kZHhjٯ*J94V7F7 '35p"3H SN QQu՜:sMR˷])U(zahZFWӕ6Au_5ɲĉ󿢵R@w6U3urQo>.Icl2;K-PJ*=فZAޔ:;xV:HU@pIz#b:cI@Yj۠#>z\ijt`"E23ͩzL &j ’]drjvp?'s*uV2T^*Av7V_hxڕC gTB.4'Y‰fƈ ҨM S~KY5m]*j "7RzzKu&PʷYR[.?m523eը:ڮT'hY1`ؒBX,@Xv օ}|*T"@-ZAVQHaW{)t!L݊w ~5z{pBzvcYzr?됐it ~o3M?W<|,es@P(+m3rR#0`0tO<Ƽ3ds1{I?;\6BIሬ@<;,T1lV˛Q Q`@^oYsU:xMo#l" t%SNsMɔ _OZIO:LS'`ldng GӰjJ #1t y5>5Nhh=K=</%_,MIi0m`]߹谨/N6 9_NEwx+?/⾛}J'O4sB%hY|h*ߎGM~v4+I6-qFwUlu_ȻsJ^Q6Rd "Ωim+cx망 [ݦ%lb#ÍԲ!8bUHr{- 69 L"? 4Zi6B_|,\/*[,]`6ڷbG=܏z?LЊrw&zi򐮊x\)9 ]pLs#YwKl7Ր¸|f$lCigFԑ4 [ěi]Rw~bМbFs{y5Vÿ1bamV$ZQ@nzNT5 &(|؏R=AyL\{UD{& z_HG}F?sjhLy50[fqͅCGic >hh"WڂL5 /f(Rnu6.V-1I/xU0Ndq/W*> M>r,X.|qGY9fX^]xRN$(Oˠ6 e, O1b"8Je'za"wP *^r}49Xٹ6;r^ Xś/α)ꎂHkF WK2N-kߋhP!Ǎ[wWk"lZ|Fq{.{὿ov_{9LM &`*޻w#}O;Yp렙ڤ!blx~;"eDZƅ0aY$L۸;{ }w8,0nжr_ E':K"ˀ+ޱI{'ݾڂry?΀ ^wϼI)]1^W2O$Tg˜Sey@gq~ԖYHXop%S,| ɸҊٛ]P` 00'LTY)3u 6ٓ:;@CRjh(eRr;&ıMB%!بX*Sc\Jp9@;82_~/Q܏ON|SR%/Hl~)iQ?\ +?"hJ[>Lq'9TQ42*&C ϦTAyPl?83XR*YI}hD`i<Ҭ8N\ӳ{(º#,FP }%Ni{ju>Xޖ(>e'!,O=y(+NMk.s6S84&=Csdw$Si+ah\VMrѿFG7ZZ'& >[ᓕ! mw+p4'WG7}x+"I@hOĸ0yZRfg}YOf;vjo;E*ؒT`܆o—W]>N_}mp&vی7VmiVѪ\fe(M@5z?rDt\ۇ endstream endobj 943 0 obj << /Length1 2223 /Length2 27100 /Length3 0 /Length 28385 /Filter /FlateDecode >> stream xڴeT۲5w hиww ݃' }={ݿ`4,UV=hJRe5FS1Pd WPفYYEA66&JJ1G%N `fbeabcaAH퀎bS@ladANΌFNjE dhin x'oQ&5`dg eR`(ޅhadcԁ 5 U5-{`5{{pSSאb(K ) 5?Ձv@GsOw? ":j\N7wf9lJpvefvssc2wqrf93O r;m5p+[휀$ARھ]obp_' ?X9+,5sٙ:98 "8:ɡ*_ꢠl|Č\<ћ,dd@ {?gfiLADQFRBMQ}@ݱcrvwO<qy^7#}<%L@יִOO Ghk;Glfigj.v.@1~!-3:X@ĂOf变 >^ { d 8;}O04q~Wt;3_w&ҾNShr~ntQ4WG F ,m$i4Ut68Ͻ HiJ63w,,,#Gҽ ބ?l̒Jb=0YIؙL-lFF,S b}gS_c`f9]}f G?G,G/,70#Ŀ;ɿ;YoE߈Ro`V޹hG1s1s17beyOa `47@.п00[?;-w^Cw^v@L 9ދ:ZQ;3wfޕNPt|'w}z8+z\q lxϩVZW,t ,LRB|% ˡ)yN*qeV2;ɀBE-TE yi^}m`l֤oS7*;F ("cL ]dG:mmc1h72nX6hӝoXQF}"+ts8c0hS u2uz?!ŋm^u?*A;yv^wGIWt@ңRIQ^)GjtGe㊞bz~Oߒ%J:cnpP[>B[D네ak-VjP { ; 0+k(J4%u}|Ri3a93=ߜ1b /K!TA$WO^ {z܇& $6w45q{ݶq5fYIJ,pΝb=]Pk(P@"qm{>P*v kϦZjvK\AX+K\) IN6_g_m&֙м/{@JH |ST47(Ӕ-p66h6pWsL@ٌ29XfYHvH`*KZ*"q:OWYdmGq 1ΨORuENz,b2FULKiXW/'3La-~C.\uYJj-#k2IP nQ{U m C]ZlyF| ;*,  -3:Ooەn\Fy9!#ԖWVte&1bJZ.W9>fr-Mh~HWfR}k\2|}` ,:ݓ=MFS-E7VbQMF|01޵QeA!dlJ`n*;b 8ą#eIڿ<}g E۹ЃPy*ee\4KEٺQu(I"-;r+ ܢ\q}~y e C6s%;uo,Z.AZ7aX$\? S҆b٥ ] c,)JA|\agK[[oCRxbM9C~XpۃG5_mGDBcin |ֵʿkcO (D"wuUaZ E+;F@evqv2aTe`1Q@7vFDpJl { d\4yfv?Tp xe.~n8Ug+J |* ȁk-mʩ r@0n V,+LGIt8p9C¾,YJբdyc=3OK)bD)hRu #=gaC`ϐV2UĵpT= G wRMCb{ 6 h1>t |wgqƾMo(OP܎w L-N?B2KXƇ)wR|6] AL.Kתסx*nr妘x@@3Q>,,p9.$f)߃2 /QmH.aj!c.{GEC0qpG;0U^ɠmtt0\k.6Цqiavf,e㒊h!(8p<~?4')b7' q)8oGhJ|`:z~8׏ҹ,(, IETn"1uImi-&l!g^]F/Y =]]2_`^6TD$)kT Õu.;QNq ߯Blm`8w]:=UmLKEnFp/(cGO@ _/@tMNģgkX"V(ЊujN2ءf:+] w;T-wXCMK y3~?_zϖ }*\kn*k1wt{Gh}KSoo5H'Ġ|aEh| c狅婳+G> gb)&ϴ:h~.KA:LZvgI&P*o l.^TQq!<~'iE 1U/74g`f@}!T1Sw7o$x0#@kdmkF&ɔO=: [<{1&-9,+WD3㑋z;8]NE&$R m%0JV=ނaq|Zv<tt,1(3X.blMNsFlYVOMmP٥?$Wk4jƈ^6?4ɸT"v:&I]rn\OfX`̏|ϣbefHd{YxU jYn ]`s3q`џ K4%W?Ͳیt8=6BFmОcϸ.Y('P-cDYu`Ij_e4Y\,3sZW|N*I Cg4;Cg[k!KsOt--V9Xn qD\",PУI60T2r?@U/ YQEa ǍI)jTNw*sp\*v`C/Y 4~ r=+M&%ݲ3 U"_x90kR98 -J\? nSqz^i& W鋓A0r޺Skg~KpZ2ҝ>f%26qc;΂M,J#Dv;_MX)֕IhެP5gcQ- ,6jM7*{eIs\o E*h^73Qj_MR(i5q#=BsgBN>B4"B]WHJ}dI+ʾ P~aOwu~|Ͽ?q"olNS%eHi?&D^s^iRGe2P,7dטWĹS]5t͵M:}Cfa ʬ4W~dO5S?f~WѴ:2kNxڄLySyĴt~ 856NS3{,,WC"ƶEuF-y1{oK`N $?wHg[F3gxlVњbɹa5 ZˏR F5]DUm#mY}"PFH&KBبov2cNTO=3sO~뭭2g[2%klC-N!\ۈN}U:;KMw 3!=5r +O^7'N"}zrS]YZz]įdnZTBa[Iܮ-?|~E1 1hCh7 } KW3eax>!MWӛXi Ⰼ1|Įa]v=BaYj$_mQCΰ>[PU@U18VQCEO=GL: ;5ֲaj5A}fL!J\<)L4.!Y@m4Tu1풼Xh^f "ߘ((&ΞLY0=j0lj `,bTsR?^LX?g'a{D'K51nn}C܉ \1r@.;86mzx*oޛ?oK(SC -5WLOTC ^l]}H3 ZJYY 0xqdeKʵLρƳVkr[Opsi]Ttp`qiEMYxe*_|o(6{ٔp`C3X!|j~3 cn%&Z'95?Ue=қY*'BN1k`fwUGwqLf=&N|Otm<|ȩ0W'A${{b4c.Voxi죧ԽWOyx$'ID *R dNaYS;V];% 6qμzU;1^ͽ9 s~8mjRC5 <'Z58'H}HW)o`z!dxȋ \RԿ%sy'mil\g&|O˓Tm9hlkXC8<:;}pq ?],R~V^ٿp=-^a5fzU= G M д;x\.Z]j*ε +rYUjQ[c%̝ҍ, ^xR R-)Zy >,$fB1{=:[N^@Dhr>B*G%DI%8j e@4_BG`JI4Q%KT< 龇70TGUL31-W@;^7ſ ɇRUGםvrL =xddO{g5Tr~`&^Y=P1 aE@Nvg$n{3U_a[ѪUFv+Uz5ŸpkvIށ? Z KMWLL£쪰:bべp,-+IWdB;}nL5dޥqR"NsE)>`!~K(imj -nV\U(=NWV!^e& M. 1vPA:Te)DxfGYqҞ*w?y֔*1 Fh6S&{Y!tN&[t ICA4$|v-؊fKwAlhE32eRh)Il!ˑz0ZQ`U-CJP09 FNb 4pfyG\N, gD$cO . ?_ʶD!::V|,WF6F7yt":q2dyXsՕJ5"q"c}kB {ą߅²x'F,|xi¯=$16#~YðsMn}W|b믓p>ӢOi"R/Tӻm:D:ng!(UZD;=)7Xms{PU!LTJP:! Zp$(W_'8}7Ѱl%;f1$&Zy iʰx>CU|w\0gfFNʢ3F nNh.}H>|#Sjl݆k8Toxu 22dNҼn!_{5>ۡ6٨4* \7lJ+%>Snʜ;BxO]`}q`y @X"[!\s!e2|#S/KiWbʝVEx FĹ]A}dbx 5IKn<*V\ܕݨnt?ƆuHCs!~nNJ%)8&.>v]]TPdOTǠF=|n1t1mVt|_%sX2G_ؙO*X w<<ϵKMz7FPsL.Sz1vZʱ75p&o{@^1 Hu$FoA=h`8|99bd5-rsK#|qL@,p1| iaW_Dc̻U3< ˥'14 %zLBQ901C zٙ*DT>K0yKyAJ7lߊɫU{9*.~ k:UX\^fI*7N/ҩeڼeD5#7|PA9~_7N W9TղEZe#)ff&ܹhD.6 D25֌~Lw_GGOwY7g?[02ى5J`MdzGń[j{GXIj nKD"LDX?y)n_hE&yR 7:-p;> >:Ml#&WIWO8D 3b8)}&s)]5.*P a4g `5'P'zB޽B-]$f 3ėcs73IG8#r /۸ȇe A|s(nW[a7R{r<s&d']6]AnQ?[/xH!cPO>MC瑷IxpԛWGAY`:I|}!53a,ʼKNM`tw^8k#=tk:6Ɔw8 ưk"wD*si* M$Wo g7>X~L?ϣZ@ 0Zy}rOBn/@Z٠|hswuO] `i rB8$vub{Q.mQBX~dhN:J0DdNMZ=P]NF` covn J'YUC˵bK:Ћ A=}Yf]qmˈT]q-ux2Ze``B2raƼx$84.FQSj޶ 蚌@?c>,pB|QMY2"`h3*94-q] ?$W(賟!zbq:)MWciMQ|/|D$Ŕ-PRdCrXp]?mB8];&kJ3FZ(<@E)\ LO4 4 xk}xO[*kd JDiټruuAGPۙ~E]zoZ>6U 9v^(733cE|}%_ eU6_u}MTmi\QQ VJ+ΙogߣFBў .Tyuks!)4 =4%7t\E5gBwd8q7ٜSZ"K}A='UX4W~dv̰OΛ) sS lKPc1{T3r\Y+iT[mFo5+Jtaŵj՟֎}V2ƤR3Ggnu #QneϘb+x%?-.'8j2.B5G* ) H9ҝ_']ZϹ( ɶ[DM#jZ'4 E"y6-nױ]~f;ĩH/E/D88{]W#"JG JLFz0ixKVG2ճtyhb^|\VLe(vѦ890²&d:酻y51 ^"˽A :`<< Q_7pXi/}`5ȿE~QZL,3WY7щ6d!>hDh1ALI.kBdLVC>͡'G̅v)~SxdEhOfqUC"bgCKi7N" ݥ旘F>ȆRT"7LԱqpuJh\D6C7*ɤeT#ܢ <2 SvAi+S@ZWp8קrXihxNy<ݿC&Ádr͇v|8ÂϓpO@(^9 H9dRw~,qc7`DuB1&g67lFk.[f*bP)$gT+Kh#ck: m|yz}%I-0uky~?G\՛/VP`@{5<{)PvVi\>=wt2!)ʦ~iƿ0l՘?i$viT1 QP훔ӯ)k4V˫x57η>?/q*JHZ#v b~2v'A fc#rMǩ oH5+ƬV<.VZ[^ÝwS}"ni[vl1WҧGzͰF3Mnހ PHv\MAs1jUq*CUFCքe z7nn@[>ZHZw~ L}7!Q~bcW ֞-~N+BΓY2٪߆]R]_"\χxC &k}tBr$>Zt/jJ-DI+wb0+-'YcH{ +vi>owZ]D%V9/Xt=*y7$Xkc5Ee?0b$2ZrRȯ) cm!Mo [Tm1nTu \ /b ;V @=[O3눰ToHRYŁ]uuh ?"ڂ;'w~tS[ϯsR-mPPus@Pj~>KI2ZSiZ5zԝ[6 ͢j}DUXn..B&l8r6mg!*kN6IkGOgT{- nJ0W4wɏ9TKS?>f[:{Oij7 ɯk_)o>*Be|X9.2xs)rvcѼ7L^Ăͪ: 'wf,[c1ooB=pv6rn<ּ h=S U<ص``8䓵o_r,о=<@(7g_M1QIc]=[4(F ^ÓӊRw_7OprSxbpyx) zf^otQ2 B}$GIaQ2n$7DEq9ļL $ ބiWމAT=] !=Ho_ 9G߼ҀӶ諒Dq%nNX$`OO, Rk|IcVD(gKl?f8,I']\o sJ:빌.izD ay@hA=U1 k;bb,zq Qʗ[JI(rPjci8잫f.Ԩ aU~jxK籍+BlȳtMtFcyAW#XMbFbj;-Flgx@Iny9ǻ#/\hHhGAwjk {1NZMtjtĝAg>9[O 5[\]2HMlVř:AXEMJnz3KZl5' }egg *(o3J]s3I`;+Ӊh~1aUeo 4oK#: iK$WE*{~U`^}pڨлB,/ƹ(7iZ98&"yX~( Oxr)3G))EJI Zrh<0ʼIҷyxC:J4G4?_4K˖a wâ1=GVvPgY!$zOL+JtAPj.*֏¯"bEe}tu"#TBKIV1%4c :<`g|iU}Gt! @kc- Q2oObf>0aGkA;nŎm+"G,.FysU ?uq+3 E"kUM݌,ưP$jN̍44loV,1鏩!PEu^4S" ^%AW<7 b-6Atq^ L'FQ !Ffbvjk֧M!Vcȥ].w H&w][}&4xHs)IKpej䥫*QL'$">ݘ(y+5@Q.w;2LR n9#_/s3?(##Èr)e[0X׳[:%)c[hej'7d 3ud7/ s^`~xGsЯ|Uvsgcl΅) <Z5I._(;iU9Td>λs d1o!15"="VqaI8i]ULK׫lݐUH|M&0G-zI4_N){|tXf!cM?DЧ+zOEs;_*/ QbC0an,L2ܱ zfQl\wq`krʓl5Ň"R@_P|P=3'q>kRYvc:wt4\H HqQK㍆CɊ/ p`ͼiY)verc;6샇I *Ӵ8[Qۄrg%l xnQH_hzS|c{c=*rk g,9sHr "PO&)׹.-} z`X"?<% hZϟTm9ٌ`/V uֻ]͘M4bU#J" (zN S yv\cG(46+aKDhBzGCP-dړ|]/X~%G\+K0PtBF1;=חb=QkĿ8q\ ,l>*{f f\žqˮҋ<_,Mu[>Ib`h@1$)LR5Q&-)6rU~iA_elGEJ}CE8prRajq@!Avſ( 0 qUV2xK^,q[ GKg³!`Js="%llw,?D"20F1o1IA{Q-ug?X7k|p& YFE!l)ЋvXp!:W {&F@HF\mzvNvftyN|;w?jl^׬jtGfyjS`X(*1Gj!U#j6ŀk§^iޙ_7I]{Gb@oG+,jͼl"杽|4:Hq4TS8i͔60@Uv~-v Wk, "mzD<@\]ՎH!@q833t{ȒEX`5雎B:ڵ|whjjg6'-E#1]L[Qnr$V*1rbN*H3/э}h*/ |nR;TGRQ^j@sU_P 3C-2i\-uPyj j6mY?]Lj yQ qƐ]ȫ9!YY$U)oT)n4՚NPa)f-i tH;LOV%_'Ani##&i*6D0.4.p/^ϔ܈*>N@v(nsqSEїA5{bD=s!\2 Iz;_,[eJ("DNoLE50lo+Ut7i!xVv Y9` !,#[5.P ez>ss6H;5 I*ӪK3 '0;a]FnekdhICOwcv9ޛIzzz$*ynKqeԨ)o Ninv68-M0eC)B9 Ri߲q2mSYu,X{0HQk9E @Ex^o%Wi&?]YK mlPM/"M(ŃWq:T+\h˓+ jj]=SHb64 Dpu)<'c8wcGr ߙ/|p[~Nmv:DRX4=+_~s5&!K`3˻TCY *sS+ϊ>J avkWtPJᚹj6I?'i(JTwRf9(u~ۼ[) zg_uLVtc^ܤw T68pKL:]kU<^ pI: ,|4D8gRM}-_(H>r_F[~FCk­Mqo `;|3t/1@Ns__s2ѝ,`bi5걻!rw;w6}~~zW/ĺ} }%;^SANVʯlߩ.,aau-*9}Uz!S?@A..0BR鞺:M[p( &qO8\͢1RIR⺙3㸵# $wW #y]R|2 W*p g$o2ۓs&=h/r1HnZﲠlzS^S/GrHEJO[^FVG46ɤ[Vr+̚mnz53,B.WN9'MOG6Kz4e]s r],ֲxu^rexK.e$$W?>loZ_\YJ_29Q#Ԁ8 r{mWmtσ՞RW$=1̛gː wO78.I5DˆJ϶ ->ã3f.I=>0i??=̑W D>:Q*CF0u/wZX3I/PDBY0q7.Gmrwqr<{u}`)j,/<ӣi6p[Aں7b`PzM2,Xp`܏y0-Ų^q( JLjYKF3レ~=zF\&.l81w24AO$@z/K͟|Q̳ eQdz?eBWe|3 SAH `1#uܲx{#*jXEÆw"_-` O,]ZٰT0.OdwkZ]Îy)o( i | co=OL2;T&ߞ12c^i(=݋aYnS%oƕPoFevB[t"ZAwF\9 ?q_Om/un]+)eϦW j"(OzGJ &#,+Z&^>^~Oj8gwZ0Hi#`Y`Zf6QKqӡFJ`06%R❂S'a{ZzӔ'6^my1齬Wa]!d8'N#&!PzVxY.^ ?|iiB9 ?n|J^хom:FޙR+T%mpmMe罹QX'AWZR.0W"NW1l-Cgg ʩ@"w2X'Bh`ɴ)sl2#mx+T-om5DUKaNL;>)#G׀ 54_űi vc-%ab7+r7Bh(ͫ(jlG .y+4Tw چAos  UD釡 sGY l4 ӎwD[N ξL3eSMc+%7a{5 &P(;+fgwo&bZƠ{NÁK2g*RAXG *j1 p3mKìۊC'Pi݅UY|#c:T2A_Mij6ߝOn!E2>h;$?Nȥ[/RDr=?TΛ;x@(Ȗlˇ?g_jy 8*Dw]I^r)ш1ŵ gOrLC\S1H yivDd +\G/Ԃ峠ݒE7FwsMw(bJڗQ2aC7)vOPHTۻAN\ճnI;q Y`r{q`X_壎/iq`ĉh*La~A΄c@AW]AM>-RpGF=NS Ob*q 8rO!2~_A,Isμp5Y[p.",MW^DVIC `VLIdhWWt\a9p,*>7vT%KZ7feCtIcbi#H_F&:Dw+(ES<)z[׼*n|Tu͟<iP⸴7b:cI=#,߸QDLhͼSc&?VΈ Qo&+HUU^7.z%!?CDlT[L7 -q;Qy+_q'ȁuO8tfC2Wi/(sJ% h}>;g@u`v؄K֘w=HC!=tWTP58/^ --Wai5ܰ=ZR7p? ]h:2F+o|X_1^R ^%M`FI,<ȁp LlK!)0.EɔMaE iRcF_hlIǑ$|޾yJaQH~gUE /"Pj*BA0_:!PF) ;WDŽp9,%qIwR[vJLb}EUi]K]uCCwf#:t0[2 !cC3\_b)QW%0>4݅N>`ݑrHnN-٘Q #}]{\B_; %(dxk58Bmn+C|6MƃDž%QTX$?vIP1Ͻ2a= myp̩׃ǟlGvӧ8毠.QQSY>`MX3|*_j !"@,uM+Z^t~Ӛo 2הP1SS''/b@k]w8l##?WlVL/@e$ٰ chYa/bIj$5!\WF %+Uߤ7] fkπ kx`%3T4Czhc;P2-g2 .k7O؈MHC5;hy>?Yn0QM"biTH98̕^U0x_ 'ZyȣWEuKgڌ}ŶP"{{1h &:t#3c-6qhw;RX`Ьi9 cXAK !M|'xݯl27\t̨ۄ4cT^ny>5U~.cÑ ! )TȨ}Ť -u<gIYh ]ilǐ9+JɜQ5T0/v/?8# ڵ|兛 /^bbN|+\Alx ~6 Q'gҞ^R9iZ-.K#UYԔ <8^,c-h!B#)i:$j:_|r2֬YaO[=HKL'6QteaPn{{_mmzy^VF;D z9-VhG[ZtN$ę9X%4n kn'8z\}2/i>-ep/l,w;V/OF6O`RCHkD>"X\d;+==SUK>#joŰj܆?T֜N$ƶ ,eu,\tD=F3J \-F1ʞnut{̒A| :#߫ #Aш'J!f\jz¹ɞdc2X4.|Y'w(D{HҿǻƄ=*-F[V&(;@Ʈe\PV5Qq$yzzoIA/JH<"m,U%xh)W8=׻LjP: endstream endobj 945 0 obj << /Length1 3077 /Length2 31559 /Length3 0 /Length 33285 /Filter /FlateDecode >> stream xڴuX>LJ7Rn6MlDBC.Pmy=3k{-65(vrqTTU`NV-G 7*-;X@B~@ ] DnP5 Xx9  ;:ۂ%`o7OnV?b(YX9=@ gk*@ 5 `g%ڲZy-u] mF6hb7..`"+Tӑ_uute@@,WՑ1Аdts)_ԠKmN0A .B잞lo!l`7[6؁`70orBJgS* +;"9NP)vȿAp;e,Yp9CV@;/К_7nnjeڙw϶ w26 G MURMQNV[U:xά`:l/?Iʨ@G_4 |2 N7kgۀm(oƅ](?PprL33T_ B[x7@߿P9 +tС6`P&`2BO5` AeWC9Zro, -Y8#"2ݜ,ry5@+TYb}Ig[G tO19Mб~z@\VN>A'_|a `WVSf?#Ol XYxr@瀋 ik?`gsCK.o K1 إ?] e ]߈.8ψ ψ\3rQ}FP.jEHEAh>#(g\t3ry\3r17r1|FuZ YqzVMo XBOݿ\N,,_t_f1; @ r_ MYBY?'89[rC;( sRh?񻾱p|eG @yy"Ph;@Ev:PA>;z=7C#Nhs)^h.gYhi7NQ~& k''Qg7>7 {ߡ|@= 84PU]߀cϚ迶sf^hw@'N!_ MzN'sY^;7_U k4Ǜ = B {u.IЪAVVPϼ5Vϻ%lQ:T)B̑=[%}ś>Fʉ;=DIDOOC+fF|4[C}\~V=8zP" 6Ljp%z&/2ư|É6&uN$VKb} ǵ,b?x6/'ʇTI L.B0ؐ6w&fieo'2N}-aPbY[Ϙȅ/Js@BmC>>(әa=g˸$Ns%.^9=6,iz Ȯfa&DD9FO/ _b4,_w[mlP831:A !Xp,t*IlBpב6R_6.Yӟ׎%**x7}2_zMoSנP"Ubnl=oŷbkT{qt falӿɻyiX|*y|XnD*sA3x[<N/'M8bj_$oit^KN a K~ɵ_ oZY/QRj!^>#DVYW9: 枖:۳/O=<-J$Wv9¡G&A~846:SX8X w: 7dB:Rt;TriGDLS8wD *Jˈ2DU*$ PF7PEE9l 凊2ivFܥ/5L<H!#7#sn|%w\ݳx#S 6&4Q'U}f~gf[ljztX@+VlYڊ섾 "nc1OzCuO K>7əB'Nϻ #eRYg3R{Mu{kxڂ]wa{ g%ڇk>OOt sTf q|TI h9Uo?@z\JS<&+ LI.cZdT1#84 .ánd>Psj,04!kj p!.KD; gqS47Ȓ"cg F'5:i/VN]N /=!s!dk۩Á[#i# r]޽35x=J}j.e=L)9k)Rk`BF1j;禫ɫu/lkk<{I2ʞڥ"L|T;\6| n7,`e0UlTd:f/RV饻bsMkߓ[#>5YL%rSuᄎ5Jt+ISx3v駋W=#%84p^Ӥ4ڕ#IG4WE)AsB$=s*k簽UW~7gzh lnx+e$E[[k2ˇ o T4 *]W_BKsD Ï[$$V7,*uUcVǐR2RGVC@,Z5uDLHeޥj#d4x{};XeTQUM"_gk]ƃ*0$UrjG FUvh~nϧa<~sP|İ^lcpôuZ5<:?I|\#c2%Y_P< |ey^IF1q'vqd27Ũj_-rMxRO-;D%D}_xa/JP0];fE?p[.}F{.ꙂU*5S}H(Z❞mv_Վݦ;B;"n0!: 'uTDF#ݧ,ZAĚXd\ߩDo[/%]8xZwD9/<4e14c_5 #-SV&\Cukܬo52w<%&kGN{;d {}݉ƛqrC4.3!IyG!çjeՅgћW&RoHN! GDKxUyVϡXD4mI6G!1=aǫneѹa{4 p%Įm@% 8^K%4Jglj`&GHIyULܹ/5IBko}z }ï5?˧ ~Һ.}g;.uٵ-Lsy8#-LjŽ0p>ɫ5w6hb@Wf>vdfS@7dXtII#3fT+jOł E ;po.SZ`v#YRV @/>advV?$5^:?ŝAgL>BAgW#w=dtjB;Fm)PoFŃ"h@e{97Ku G"NfuXRtc7(1d0X3}M GrhwOl07q+]J+<%鸸s=]*НHЁD ~ҖId1x;:/8mdy"_~M'Qיi< QR@KO݊l򠾆6leΘ8zU>:(a{kn]Pf塅O:?buo¦| b6%>q.d\Jf~K I(;)u6Ӵ6>άK 2}I{9GhIx6%Pte3|aWrD-ZA3֒.Hⷣ{G)Ulj $d^1K'YVՌ95 ^B)XxTyM>lRD,&_Yp=>u 6,t j]gǛW5& y^}hǛsur,r38gbH\Jk QtOqo#ϱfx2ft83Cus0,en)7WQYGsg>_4D:z1yŴ\~U'j\Eq-^`zv6kG= AˇU`K+OfX KNOdFc._}>Sί/Hљo0+ra)?HiӻjŞ)ܢ ua/yj^xs")9MOUZ+T]F⒇ 7hUx `)˷ Kr Jqȅ5:e͡P<(}̝U 3njhvo[ʒ*z)˳,~(رYeêY7'q54V Ō؜M'!>)==c+;z?t|2vDvxWl5?GwgJ3;||Y\ԬE *G]`5 !v&mz=\c6-ujs<!M?=Urn;Ui_D&[Ò.U*[|؛ ҬVxo1&s#IdM^hozrN)I9l3e?NU2.!o FNÏ?D7.k[:EdpW;CRs;eh|ՒU^'U2GFL'åxye T*ķVr%'O ʥlRW Ȳ*}v+7oMq_YA_ƀ@IbhO}*{h VU!i K }^#h)̈́z/W%AE^RXQ,sC.v e.uۛ0gBqަ`B[ɿ)`JI7]  ↛D24. z7=۴7'̻<ď'Ϭg/9,^Y( 'E0_~OˤNkmvrNqjQ ޢGxg@7݄5+?sVLwi.X* H ͽ"wgbg ˠ܄%a5F EH׋,.meȁ463_1L!^MJjTJyZNTEI% %8Y7^JiӀшVS ò55/H.=%CҍD7`Y, BEzXKf7ƈbq(\”_Wҥ((<{w8YPyLyqjČrrHթ|l D~C;j&\;|YJ$a_|]䃩zjE]_ZbH*1OC^`o5IN ~c,$gg.&{*˵j+fbn݉ھʮTc_:peJ2p_#BnkZs~/!8ŗNBlݚ HP(*ť72oMPtUPFۿAӮm- hkeIY^y k|ldž!yǟe$>/?!O pntKo2GG>;6L/-ǣ'_XyRv3젽p[`\{!6ibV dh+j -Ș:ܚ1(.r6ќjsB1H]`! [k4VnCI'*ݧ LBݹ1pRJߕe z]D b2,LʹemR3)d4i5ټZSv>u޽C>6~ؚu Ghf,?, 43nrrIiibcWIˆ9,@h.DOCaC~*X+$vG: ϸ2<ʀe9Ve2mv׬!t$%Yf\ygY#7٠q'B%^RZ(ՂiO?X|>ȑ ́O0O+.ꫧ R;lz\TB};K%{DhAcF:|SkU,i#%8S4#IG&r23X>}9\7 ?aGA 9v$H4IVnv.Vl"?lt&G:Rs@QKTY|d*dQ0ͻ J R M{o=[Pm`G,9V$T_P0_tvVK_ V 铛H0/)ɵ> i"vnAd6>W6#<2d SƧ>mB^azvE{P*UۧVK zЌtVKYcOEf8E ڋz #E{gw衤Ssy4H P_!V(u_>u/[ 5.F2>ؓw-{bs"Z^1iWni%ξuJN͍F $<^|۷s}s%8ZjGV`i0L@w'\Ć VEo\"S&v0{Eګ9RU^jd`"mQ HQyEqy:XsĬȼӋ,Odr֢<<;n2N =e{Fa'(\ޜN,W_ZV70dDہbA5SV??\-[OK+iWO+;,).MVNM~7 *zSJs=уh!!)a_/j@Y`|}Ѳ4m3yƃ3ֱ@ʷc8/F2 3uh0xr1ȒJk ֤tY@rLbd+N m? CIT Jpd$#.y>Ol8e 76sFxoU*.p4X'uuN̄@< b.0R??3j6P@2dMpu]1d#^3rY2?`c3NyRPLW#uh J/Ң6 eExJXv9 ;!UU׃>r1傮UCSk#³Kv,睧r1 vrGg}S2mkx7֛\2,GjGK]ݓVX0\v=}v5wZcvԻ7k1v js 7Žv0_(L:AZ+cpj)%_{IQ5'e z`Zo/J.O2H~x DmG?⸺n1T}Z,hAԕW}D$W +rm97P"&(0QqKp4@$QiD#@YMV"zK ,qԓ%s,.үM UI-j{[BbFMk#Sx#\,g5|#2|?|O4m_KCч^~T#DTnv{גM}j70T8@)gYMMwáOӕTaJd~C.7W%KX]zՠTjǔO,bq,8aWq@v_>^V[%,ף5X s~tN=TLABʍ9c^,> #5S{ڕ1#LT[pIG-b6ݿ=,…MxzOO5%Rqc! A5_P bryի 41FW#L]0w yL0Gf^S.D(qH!פLh-QH,)?`tn|z%0II@k23Ryׅ'WɑL|S zZuTPi#p!u,4 At}a͠-bznK*EjxaO }(o,‡C]z7G/[Ё+>Ia9WW].QrLO _Z_y,rkWF!V#a#~K,Yx)}wA- ?XߞCWlQ{0x}R&;Zcȝu'QzGȗx>Q>ޖ $K4EI[Q2.[inVx9 RY?%X(M!GoM{ kFee[ jB| T g5`_uҡbՏsNgf7XvL|w?`{dSI(B̨ntc +koT(f:׼ eC/ˌ͗{xnb,<9 |F:d lK~Q*%Ip/>(&LEE1euỴ#=Q$l6U/erKT^*?ZJ3hƖ\s'dCSw"2b!g4iH,GX>""pkm?wjm0Y.@ǹkx-gib HĊ{ڂK)H# !·218p/HS޾rКb`Xm1 gՓHVz[vAwwv+9e{f[^1=V-*׻ ktw܌E!gҭqu.Z)+y)-'|w3{(L=bWjdܡQ`c&Xb2/ J`@^eLVk2j_GX%$âMe^)f@.m}]D ֋Q#ޅcn˲.èLy)ngZߞb3 ̨x/'>5d$X :ԣ :"Cחq Xi,G&Ԇ E¨M25̆pkn-I$ Z fYSu[o1/4h Ew~OC9ajޘ@u 9r{T49W Mؠ@j¼8]Γق9E=|/:ђ9C*E=b_m[6pV9ϟ46iNX{? SlNI ߳z{aJ7*KTqލo"N(΅)@߸l("WX5?)wC?!"Uʦ80QP}/LG1]ԏ Z 'jI9_*1(IVR2/ fZ~&Q鴓}JbtEr{brk.;ƚC `NQp8%bϟ 2iR3Ǘǚ H4d:<,H;}ᑻv<_#;e5뤎ҁz={ba!3č:jbzҷU5H i>ii;&"Nz~ VR YʢZdYh|bl 'ɬYg[̱\"r%tm&أYҢۛ@N-5 :;BcC3D?i,8X/,\lJ<~5g" 6k,QzYڟFSQޫvd-u8d~fjq c[ZT[? \`P} sIidkRWvhS%h1߷cdX:gн7>9*TqQQ?YWjzS+x Mґ! ˠ%nAԟ iqo^o1;9\n|9٥CJ3 z)riIj:騘ZJU4eAo@4]B )Ď?` , 7~_PDH )ܥfKU/|t7!έ9ͮ˳ 3 |Y uݟxǐ=>Pjty.иxc#jM/i D.PtY[!̠b/3в]sJhizen-Sh)F0&I_y;D?b\lO|sɀUqK4r֑<#a HzAF 箯c0x10fA!{ػzڵ֍52k]K/&>p"G/cm׀HZM5 Rk '^Gjop_o6lr!wg791DZ#9fŊk'K4r{F0D1bMNoX]Uc6[g~k3_XaJQ'|bf=y齧3bV]K&-Cөd<JLZ9 qTM4a?^e@Xa=p-j,&&SaW~YXBbHMGP+fђTlLӵVC"Zr`Ծ}CM w/ C\D]N2_%2}Ρ$ЬQmz>=&N5J8,槃UD6Ϳ)^ϔ#vaReY6;Mס U+ٯcaaW>xKE_<33p6ʕ>j N4VNqƝtu$J2@c"CK^@E{fVGNX M$ǁ0ҙ?0i ׻ K_2'F}V\x6]HJ49\J{8"7O#zNB~TI?gA78fkʡڱ(>飁N8F?FJy)?%(ϙ/. =5ki"Uf2Svw4w^0/˶ [u=,r刂KԀF}/q:mT (EpYn "7XkMqm..l_s0 )`C)2ڒUxxi?[{إ[TƒJV/af>$К 9EדyA}"H/J3O%RajQ2/B7h57~i;((NA//'> I2KqFɈܩn@ϞuS{Ԡm7\sQy&nPEqq! e*$N,B2>NG']Y  <ڢi(y@&OS*e1^i6{v8$HJ"7 2Ŋ42 Bafr%cMԑ`+1vxX!*Uuy(mg!UPKx;L7Tn<|u0d4\fx^ C'@2^Ա{ȸDW$f@IWNEMYU t~c[FED0.8QyҮ3b;ClL+Eykm5.+MߗGC] SgZ#U\[+D<մl5]FBJ bwB^J0^,/蘍Y9Qr;&c %>ͿNVAP3bA ȳJ _7 {U=u+#| "ن)9r?v#)h" SnkA%CK>JG\qp6M-U_|CE^3K8KV}4ޓL[!tdJ)# =+`y`wo4A˨ L[/R57?BP I]d*; *uz:kTDhfe]?jA} ˪Ľö<@*?'aJT Ht 8Hlt>t|vHjj0:Q۞FɃF&*~N=U!ޤvϛ'&wh CC`#" 9vWm'Hp d0E|n.rx3Yruw p^ߍ* Tsv~>x%18Uqr(G ӘiS",~=uDSb{I~[F$wEϝ.֛_]%&7tCT%5q:A1U`a(%Gg7v' $*O+ V _`R,xw!([(Tp&+;w.څOy܃:dH|Cs׉&Vp;&cMb#-}]+51^\ `}}EGD?+ʬ}L|c;,gwc=zЋ?aNt!dql#:I֮S2_8pOې_>щ.lٜBt(' u0a+Lͣ 5 赻ZX[e0[ĵ6vMh=?"@}ЬfǞ qU_|@pE5S@3dDSnM- SU; HH 42( |ބ{u4X)6RgU<]DUP*Gk XA0Shm1@aiC6B>b\&IluZ&X\>W?W{,pg<J&L^%k`Ѳ᱇LT3#}Gsj'6̈́6:$yxx :@ҿ[ FSmiY RQQtkpEӽ6u$$j=UJja@ uTTw}+mH0t-=ѿKհ֗X ?[#66^ vЊ3IVCz%L*B'=0MsH%嚅-ϝ'N{Fg61"~2~iǿ[mX&: Iһ ~XM'glm|yD<' 7+TW3FԓԧJGP~pKJeo.9 4c`\̸@%2L+HqY6χZߨzJ}Mzu+g>!η t ,Hañ^]ZNjcŏtUDGUeN+Z8ʬqCu*ud-pǔح$l;ݩw=y6/C#)YGPNk.||~猥}H4JVCpjm_~6x6PB xq7IȋAEifہmmu/\x/‡8^)d|X0e$DQh[(<*R[kl})(bR~G;EKGC5g`*+XaZz §e֙XPXn}6D? ϣ Dϧs īq3 9#(4y`0/ q\N%KzCOAR=imOAf齃Ugn" HOZХ6gQs/[ioFѶ#ՏŠ?RTl %7_?MƫG,fū&UVX(WM\$^&d'?]zX'!K)MSͰSb j_jDo%Jn~ G/&V<.W( hEL 2޾=}IZ1:S˶QIm{[ +3h{<C"4D9 (tVa$B 7SQdkݜ%zkF==kT̷T!-6ac]FƹTxBI/ &4]5ζ{tduUD> FKp?40M*_+/[cĉ RvL͍)w>!Q lK^еR)ZiiqX(ڛUE{Eu+]n[A "U]bM -7f#fHV6.##ЅڹO1lN?F=񫱺֦ xv*JX4q 5딥nPӳzdͽ祈U z x%nU/!o+Qp_DžFMy|8|Ep` A֗DCirƙ5b>$KŻCm^ŽvUilKq 3PVYxl7|A'^) ZBºߗ-lM ;X \ gOHi>o^1ZmPf݁KiDD/X-M|@.q 4QD\VIK*xA&cE=O cYepdixlkdĞ Z^]}QD2S7ރ=X40+wXtW`g婩 #PttY $2Bc)7軉EH%)Q^29Fҕ_—  x *5ユc,> 7~e_{Hu"X'^.Vɓ7K^PTM͏y׉DRWO:N3 DN!l3g41|ݹmּݍ5 <\31O9VuaSeHҶ%Iމ}s&Уk{e=̩d*Nh@7' oʍ#C< S`M WubKË5ҤfFmXQm1nXɯ,U-sBb_qCW[8qS\IƳu1I"@\y[qK}I!3I XvOX,5wYF?'rzvq L~9#)?%oৗI{tRM7(x5VBjxٕ09)a ﭡ"&i܄UψA:)v})IE!"V>&4@,~n򰛥v]-$-e/N̮jXd TrXD6_ q48X}w˦θPY``,iBJ'm!$oG0oGZ=cw5K ƪ >aFozeHtO ōkK2 .BKkĻHs}L~^&J-kNB&uJ~Z.T/옪 ڣzf|bU_ :O.V)]pݘ5&# |-KV|31`@!ᆷ};\(n/{oqKvm ¦^ttRN`KTUGJ_oƘKOih0ո_(!-h"թDآ/bgJNcص=˱Eis">|`IgmUf9D]*} ˋaF/ 4[VYD:w75/)ղZ"/`F/έS{;10F'xir zZ^ 7q%d}m209Q̛ St.jN]ۏl_zk-='bb?w(*D!ho*_ÐSj0CH@W;ҴI& Er 5 WH#p/?@14fXGLoDe2MrX mVsĩBݡ19G.y?|Տ߱壉*0$iJnEP>E ɠc 3MtMrMQI}ѕ2 !;`=1Zy&3,bFY0aYI;)tq鎾A|bܕ~ ؉S*#*;`@$3Lf%D,"mnf:eӶC'rd& kQTɺjEIMcRG9?mxG [^Jbc[J5Q|zHUaaꅑ\ERR}Zދ(PP0=QnMʱ,QomX4~=Tv m [>w^5ΈǠϻAě㍳1֛'(>Z<Z`QCs+/6!=7!1i@S ?{hWx"c5E cb \9k[{(WgDH0x(@UCwhmTK9}T#4BFJ,xe*Xj^fY#q5UR%3̸ޘ"6Z=AޚHnA$;n;xRVT3i<)vCbSi}̉S[yr۝3<Ÿȓ NG'|xg', ;>cR5N-XR/Cl!>V"}䷘2Љ58#xgڶ\D%E&?Ŕbޮ ^E87/o0WwY·+>%醍x!C~ wVyyIh(#A~Xځ_+B%KN)8RY/Xr_&p[E8-rYp y*zMVdh_$p#ͧ$,Ǡ 5vc,$̧2Lsa=dz #LQ!ZH@[+E`frCzvdI@ 7 Xă[Jnk#_kd)~ q|RAKlA9(|a(Kkk0Dy ]MgǁX1t$ ")Q ;*m[) sO#$`9GV{皈` ƿup5Pĉ*SL[qvD"1dng.-ҝtȉd,'0-z|_{Ar׵Gm$j7L ݹ_d9r;fXL9f$:|Y~y>Fl!BE<`55 *`ǂI8@Go?nڼ5jZv+ZBW6Ajepe%vvI}s~9?ݦ O$y) s|qW@$$x>C7y+[Z?>^|@kMvqp?f<%)^o7D;-g:%U8N9yԛ,;cc<,6M;Y:0gְ;=nBulX<yfZlֱҜf8ɣBhPj g].–%3Aacn$7a?gAtV%{xAH(& Cq8|6f&AYO^G=k]Wb x? |(跦xMaVݹTqٖ@75eի}c 0^'f=&O9|_&#φM*a5K&:O)0a#@jFv;d?hH܈:ne !ҁʘ`UUrv;̋phT=XW˳߫a;FB:B+鿭~wX9 WACX  oX A`&^3gH([ _WpRB%xky%Gq3ObZ$uHAx~v*ʍ| Fb(z=N>}|LuXPst 8""~Ŷ$C uK#ɡQ.Y- 5$o5H>k8@iU#[pM9T0yխhK+WzzФk+amZ/jk~l rrl'zPeQOYÍ.N:euЭY3>ڑ61 Ǭ`{jh79)TgЙY =g[G?8ti{._hwID+@n+qsoTEj|z(;4nPZj869x!DHlv2uK\T <}i5 Kn,T.ÉX聪@Cw%Cg /{srb+t5AxB3. xcB}|Q9֟4qhETI _,x`6/$;ټ2MBBcD` 'Gf:P>.O6fWd/X?ipoC/oiY_dwԮ8b8`=W{>t)#Pd>jOմ{;ʽ-Hd컪i[\Gt/4ᶹebW5Xw3l _3lUk hk9:}Xm6wE/Y׍(#ڤgxZo+/T)[@If+vu*ցT362ȷp+j<6N+°ҏ䶗9,?H;-ϋ頍ЗV!ttܫ\E?'v}qUZoٝegɥY bs97x[KBtq3L vKmx~6%2z] Pi\uTU(gX !a l0IfJ|V+;1^c_ rt`@ 󧔈.f؀*+,J_7 ~o$^ j>|ZpC$>H9~Z Ì>#;*VZm7s/f/msX=F]7<@šsIXV `{ȅ΂p?8up=k:q_ZeL\ v[󻖅  Suh)d@jD']@E6`ޑ,9QzcDܚ]!0;.k@H#bN%κ?M?fA٥/_>gK] q P=D] ~udپr5lOQi NUeW:K;ŐMѕ$d,#x[zp$UV-&\H^$$^A8\`yI2˄BHGwVH&< U ۪ X:'|BsXm@&0m~̙ɩ^3}ztWaʸUY&&4|b@&˵dİ"G@(J *LEc>g"6nA&?#-g(Z1ԳSXvu/O"X=:sZՒ 8!4CΔEpG;S{ݨDTyyDKCC!u{](mեB KI$A~}DL{S8-Mݰ+1_K|;:T,(3(}2q6i^^ʾ\=%^ն}p)n, ^^\qޣwȴ#QuMKn=V܁*'묌͞VZ!8ȜPq-YxQ;o{KKDk9|_'blt"gn}mʱ]ıq'+QjP9^B:ĥNY xsS)tgp*1Wb*M,0 ?Xs Ktޱ7.7 ,0”%3@l6)wACGa(PwH>5 q֣,@ :d`SBl.Ǒf,Nω$DA^2cG/J$\ֶYThj2$0,qP5l6ٱwK牃w6wKugkm۳i)? 62l+JN# yĬz_ ^ ;+n @tR*^c[, d].otLN,~4J:,4 +!$h[bFupjxU:OB4KvQ7p[hOL/_Q=t/3_~ɐě:vkDءxV)@@T' KϺ4Jl-]FEHA~t;蜕QL7EX!wṯ E =#MW}boǍgA-ڇa I0EL`_8C[ Ux:hn9?}5`׍z-h YX}yuNzU$~֛IĹ < HA^8aAP«o%2Ϧc d'l=>_0ܐфu:mAGiO`*aS -?_-CV oKPB/, wtPjk“FO+E=pAvn~9G]LBGc6Yd+*SElxq2^ ZB{"$J/չS0-r}` #ф0 ZN Wlg-O1NK$&fx:?#!Q3;/8=?{ZBhڛft.#wنF'z2@sDMF>sm&߽L)_Y=%Ta,D.Ύs[ࣕ+%ߡg_xpya\JlD5*  endstream endobj 947 0 obj << /Length1 2234 /Length2 24206 /Length3 0 /Length 25555 /Filter /FlateDecode >> stream xڴeTkӸ;C<vvvJ9YJY!i{A>,;N /'O-=Yl]WrNV ߿LҽQKh rnppP6sOG矆cÔVh?:[7i[o_=X}Ŝ'HMrxcgk88G>N@777_*{{J()2e%dusq\]|X߇ >͖@₩rw8{@N "G/`X$F| V߈"7zn7zqXFF-X߃ZX@?; @N?{KlYr|7d{ ?xg-3s|gl]f{@m\띜?wߣpl{W7dY}+ lY,ֿwa wW=PY%3wW[o.F]oqqEaxgt8_Ov7@7aed!.%<@p GXW> jt!dOrHQp[P&uHQ( 5ةD#fK5B)\mfL堊rCR̎_Wc7^lXh݄oX f_VL qa{ *R pc BqQhV[ra*e[mxq0}l8uG42C%|~ad@ Ϲ1t|~K4:0| KW&8?--5d6pC*~s8'.Knfayt-d)ثOa>]R, 8,xSSGii#oasҒ>=_H`hCɝ 0UH\!1/yUdXČĕMH!HEM%FR;|Y$/'A&K|LT* M; Tks .ͽlnUri]q*F*bT[ʇF0MCUL/^ =-Ϸ!J  ْ%F8 m\q :-{O2>/ t-cxsa*R'#K4N}gs:WLJh"[M?n0ېؚn췃ءVr~~x2BǓy&1AfE+QhO K ̤/b` ` v%[g ry?aPx$3ĿTX.5CX>(aC3g Zuа0nNhk ݸ˘|PW"7 ^x A: KR"Ň920UʰlIJƩTz'Xfd:՞z#$[:#~s{`))'/M ۀW@ls‚`bf@MH'"Dl輢@ᆅܱ)-hd-6Y3iQ9R, 'I~`.*rTL.DEknW] b%';$ l}$κdAC&"UK$KL7ohJ.z/M9Ĭ8zCaH!a`PWd4(CmKqp&p, U-ě%1fȱc]m%֎>mԲ#[~iO⹄Fʿ6*R͢6K\{ iUK#<;eT9zh#<`Wh|j1*!g4T>.+1S#y7K6y9+T|DG/9a-z(^T~guYmiDW"Q |өlz zn Fg7PjqM3[BԎz\O ^C^"i6hc+lnȚIZ`3p/P<=W9nVaV}܄\)}[Mw&9Z7Ȫ̯b# ,L7zxtb B`?އO:6̇at8HP@J85/LD?!y|$t_V[I^E#Y2$Œ8)VBb#fw8UvAJxȒ8G+Gu)Q6V8$*dC}>5)'%UЗ{零*9G3ۅDrIjxEg{7`>]{c,UΆ,Lδ 13^>uJI銿>/p*BbV7OW.05+q=`_bx^CmE=݇!F_Qd{❈LU$L7I( Ԉs}M#:?,>7wa00=nE[94MfF,I[o(EJ* fh2ZwICHbk2{3㘾2hǘIF}+=o'6 =gCegsix[p؈h?T WQ9]/)La@>GGeK* ?q;S(h V-R| .p1A1,'Fuv+Ӕ1߹q5]POenyiMQF _Ҟ1j?\kpU>+a2APb{&<߼V57^Հk{3-,tqGa'hv>E 1%(_j4\ z-ĥ ѤFagɁs|q> ]̈́UapȯBã!x# dXLaT zWlWFZUn5ڂGOMhY0IƜf9.݁{{*{9XwobaG LD4] ;)ГwdeFF DG+}q#Uu0& ˜,/d]J]չTt낚tOZ#5 Olzv0?"Q[!IxEM`|| sg AĮ/HL)BZ٤ QeyVa``!M\=%ooN'h)kG.P:m|$?Hf9h[gFhY0L*;Zޒ ~vzD[>DD%]z/pKmmޙex" qiuۄ;bv Xz^Rlyp uд]izwdh&Ve^$]MJQO>6*V9hٕmUL/֏+ԁ W"4V[usui2C('>^>_iM4iDLnop|S$g n혡 "=+~CV3!V, 3]_+GNũbQ=5J1q2Vud*>v,AqrJJuF'ܕ,C5I^la&2a*vcމglCx- εxPcI"ojJ`GHAO32RX3'CvXt]oLEDz?g]5m7:#dC=|S&b9A ?`aVkmdϪf[`jbAclI[;4 ơ'B%#gv84Jr;QTfOYVDYR+YCqn?).Kؒj"vSHI4JDH-Ӣ?,~1bQ 7CͶS1mMO$&%>$:=|̣G˶i'tPB@U[~Gֆ!vW./7$^OW_G yQ>[>4TJNIۅ&Gёjbt}k57ND=5.C%y`/9 2`C8"þC̟*.HqLsvHz̪[%Df0҉njn9|U4x_3vdi+4X`}jpAdu;wn~djƃ!o nj$m>r_nƗ!}ƒlR-~T+; 8wL^1HjXtD n2ƽaV70)#_:4K` G'jÌ$ӟKK 8F0\9?e3ǧ>,r^-2PClmo6t4_7jAZZ` l2ܦg,pcu߭ Ut"t]'K5DF<ޚxAio(KM'%u #W 1*fꀓ nRMwV/KK |X:j%(?إ[pL T蕼E2W3_RTE9IOFN۴8w2"idvֲpv8?#7#j㮴f-UTLFii6/Wřa>$a߲м"^ȑs&+Ù3h! d15vc(A\B`cDRk^[/^HӇ$K NBz2דńei/)_t'hW{ n%kxgd:MPXk~jǼ67~NRkZM րɰf{mJYњ!>БȊV<mpZ[y! ^+yϝSƃe9F|Pk9tǚrPEAAy`ӗV3xIY4 䇪;ڐ^15E3>83[Ō%_pL-fź xQH/选~U hှy;6sܫ| 9HP:&0U+.MndlLi+gYAVC>U@DSu狶kvZA>[3Nt}5AǡvEIKHzb'1l"g. 4/7cv&aiVz)Q5''-@s  -p!/7FV{2$xlqa6=Uچy@e Ofn8#qTY`6gpŔ%bn88- \*^+}zj1Aekm.o )^CGj) f$xT\o,y$s^X\`0q6)Լ0RtOG|B)rl)X>nB޾I=SXl H?r`z>Cb1Fsh+KL7K=$A?k'٣u5*ꌂΒ32tlt"sժ`:(ap9nYneJoњ:~{ӥĄDL^ oQFx+T&nD%cT[/OE"{:Y Kn"6(Uެ}t>s3 ؉BY{wG4E(_ӿĠIr`$bFlb/c!'}yԗл@'jOhcþ@N fGXIS"UyuKWUי T~ڐzG5)Z\gn -G.'캊j`6*1/TxF xMds! 1JcF*n `Nl":kEf~K=_'KEڲz]Qh,,DNWoTałVKn/6\}~풚ZePq~ ]:,UYI;+Ҿ~S^Mվ!.g~<eW%z,.Mۖ)эč+ڒ6 X0p:w@.,aݖQh0GyR-,PoP)Xz>ځ'#1(J_$T* Ib,D3q Ț{'Wg} z^cp[EU{g)hsٶrVc2c)p'_lUGf%W)SP.#_lG{%QeC+ 5FEȭ/M${ک%kRkb> L{ `[sofADor'm ^eѦC}˭:Qn!㲪h>gzwP~aL3d~3M9 ayf=CSXgVVHN5gsjzk DMz4sM(ҋ!])y /rI|^eV&)q@VK0ҏLvقF]hOVm]'ِf \GƯ5;ZD]Ihڍ ˈ!,ΛB$\L /7FC<U&w$8s%c?OsOh~43-ZAuVq >~wQem<"Us%G6M)H4)i/3mmY=:>!R^<,?͉"Trk󑑿:;CKs18,5kVt h2q~l8@O5+Wg A:8}|:WhLS؜ξWfdyN:5/RKo۫G?;^oǕbH].9C;\D .h I}^ֵHSY]xȋ`4irh:KFS!w%+B V`1<b UT#l" >hQ$߰ a[ 6Z!fsj/z #C("X |&ȗ MRAg M ;!&7}F7ɘޓuL)Z18+niR n"n{5ҳ"%,sKoe1SNJ$ZVy$Aɺ52x^L8,E Jl|DdsG1gxpF{uN]Y'y4qf,ZN$ʊ%6o侒;&[3#-{HO*1,+^@ϥXCPi/=e  }Ik:6Y3#1,__A0=c*.󴅺!Vx1~}KS-mSA Po)$(2,Up+՜HuF> );o܂}Q{a6J\v4)W<L?V*vͰù~$#E/!`?|+hj$ؤ~.(=*^.ԡQ kHA;sڝ Ȟ܊XP1SP:n *k4#! 'w]W(p!&jV՚gTp*=)ZopJO0VXs XS~a4bN`wǯ'ZDJ^e|XƉ/,ˮ#p-4}e92B `B?m5(Gf7*ap#Bҟ6S `B9tQ*%Ă(Ɠ,nW`\Wߡ$ks%B;t2!MgS #8i^^}狸oAmW$24zEW2t&U8٣\ rV@n ՟旺"nºynL=墾Z̙Tv[CyNi6lSxl;  MV?6SidkR,J*/YNu-I`V|2,z'0rqJ,yfCqqq23⾴xz4J#cuB NF;^ӂ^X&DaV#LUK &}Ys"[`d <Ȅ;A7Wt: F.^6' VO*5͌V ׁT%ð͠&[tJip TN)"}q{&W&dy# rt<9ә2*<8& V+jD:>eA BI6Lj "v4YiV2"I*~7 $HsB2MD< boX?yd#<@?p]hV2hh5buȲlЅ%[bBX@ٲeX a^  ~m)&pku^%Z#}g]8c7_Q$eŋ.Ƿnځ M Ȗt?I؄6h6wrRo ?[2 F kǡ7"-Mxro {vA+'OW~odE*J8r|0R.j>EJ^`Q2$fidnVG4jmJ j?_nVRfoZTi{L;:̎:mA^wP[jG8֧&(EP*΁b'ƕQJw@W^rf [.tě+/k}Bs ^%YQ?Q]kaSVG%nbACd (o:]PKϲ,ec>MWߖBKD^Ӡ]K`RΓN>8Ybmы_x`ׄTpj IYOCk?!ujn~cR;\̥3#WQI)мeEJ<>b;/ڧZ#b~)Z{WO_pv 'JЀǵހjZݮD~;͆fҕkqPc~dQ׫.O$Ao=.ͧ|G`dWC钼(VreBx,B۴l8|{xԈǑQ9D{Q9O A9GnG\+j"tg}_픸 v.3|<ѓP/k+,nM;es{g)wZ[ߒ(E L po{%H2̥zՎeSb['<|h>&Q4ۂ~DyJλCXDUzj~G;H~NŲ 20{MX=r9n*}jeI]Za8#|MS3C`QsKkz{=hx(&D?cOa'R}8)`3!{7$`5 ,Q{ H2(5Z$Ӣ2PU8ڇm~Mu7r{YGԣ JZ!r)Bxaw,k ^Ydriz\ 1p aH -rA80LbOhCJYYzlD?$ 7l13jyPJrIF2޸*W1LJ[KJ nNqvnp݊ ZF"rNQyٗG.^>Pm!Fu!a T:OΣAȭgƊ8ALq{(Eè(.*t0R)xݛ(qJ!كũj &tu`Mjy VԄ,zuCňgdv8Г2JF׌ J:YD}36쉛gCk`>Vl/Au4D]e3E!|դlN5qHruv "rx<,K 4TВ>-T``a~7I[u tUE|r+9 JSHVXVk|-\!^HP,-2weư̳t5vZD;PN'_^ פ'Bhii:B.fpXkKeکmDn=2Oʼnj0/RX>:xkf-G]Feq ر qVFy+UhS-*c60f3;CjJtOw|>2 6Z83|J1fZ OslH^ȕ׮?WLB:?ptd+/-N,j_Ѝ Oً3 zX‹BE :C9ʛE> [ >5\Zvnqgі([E`a֌QIy8 $/e?-}:ˇ>?5P'oeZ>m#<ֲđ 4|x\0N|Dp $cSʋRYxH.u A$]0W)w~?qu ʴQfRkp;/=صPq;S[K2ɥ!%S7ذqm(s%lGzzJշPw$<|R5c SI1g v }!{?xdzSR*rO+g~0,7^ 0l ɹc;(oDWn4{~7|g巟S~R=Q&!e11g)`LxxuXqHb"z+dF&9P$`;G"}UVhMU ThePŅHb۽9x},4Swgm_*QhLovqܤ$Ǩ^`_>-zccdG]+<3dBo9Kgްi徼\!˭nb%yBv}O C^f >M \o 6tAŸ:^ǯՆi btd Ruѵ)U6\~-ŀ$a-Z1!?1v%)jC⠪0ФKs .S u.+gw#LWѰ =(Nzy9Z7At5~ ɧ%-K&cuYZ0T8&[Wa]utIsbe'גC2əz6 `@ Poec 1~#KBBlnJ5LxRg $+{Xk#X;!Y"CkhXx{ރ;QD:]gBoKr?-{[{1әA#A׷mo /"Ji75FPXd\EMVQiV94M*hmp3/ IQ^qEn}|u`5Xrt0WM_fg;]ibOAV+ugآ_/>XWvmd.JهGXLj,QU6H}FNfn~P/&Xt|eA'dAZ4o>KLv\wZcRb{˰b*;t0[ĽPz(e{,?DAYKtPܐ\re*ۂ~:7Wn2jXEɐM"ea#d>81F vc,䴧xB?Z/\"v&oդ"->Bzop Pp,5gN#Phj(R*/P"fSFf[\[MN8 !RW}X!L3(H2IͶ>q XcvT.@d7 7hpSEy_ƈy ˶gM[T{*Zvdߟb s/c9 iKmP,|Eu9ikb<1BThlj\~!V9trzk bfK:j# 1{ 1˰6BTkmg11Ƶ ]B; m9)گŻ0Cf"Bo`<8=(-7?\L>6(4949h=^jm,/=w j80Fely^8BڡE?nw 5y@ZO~)[G k΁"tj"qU24MzV+UG2pe{q;lq0ѠUISxRCH 2㢦*v_!pIkCF?âQ 3f߭AL9I8 m:݄d)G4:phʱdSQ9HxL-1Sg;ü@V0 _mAqXgŹ|!VS~(5ݾܐf/e_ẗ́,m:9xw]~Ƽ[|kA `s-W n741¶N!lT,40Ѕvq;>};"=]"Z <AJc"Eᓝ_-ga٣:Uy a@Qޠ2Qo5HlBDzwnp,'9+ ÒuG4]oxCNTeugcʇ(&řSRKPSs|0VRSi$=!)ݱ~NeAÂ9QQފ׍JtCfZAB.6 ҆C UC/3;'gֿ:~zaS݊àKl5gVD; =~7ඕsܣt֫>NO mNe^ݘ2!F%errXA5ϫ׊S ?9$= t0 Ǯo6? oYtX(+1NOk=K돕Wbtb "/hCkB"g70;LcC ۯ- JdH@-+H8, 7d>6Tzf=5LԞxP,Y+cFP9gxNS?jGaO~L c>u9JFLTՐwĶPbhBA&Dž39cٓu 0\{Wʔbyjj n_aUZLi;˦E~جYU֥ĴMG}rJdv?߸0Q%렼}d["VOc>>W2%b\ Ev:6&_ 9aF5:+lxz%sMmNpgq ZOͣ HəϒI'RwzcUс57lA!oƼoQ3]Q JɊ6 luXB2Ff2 4ǸI+OB@bDZTITe^|VbyrW yKtR@>P;AFzI_V[b7glR2j"Onp]>P0nR;rxIS`h>l̉ V7͢'(L<tl%"ia#p Ƣ&;y{J%Y$Y{ZkFn;\:wBQۨS06jb ݧ]FQYj ${IA *ABdnI.TtG6vR.AbZWVfzu,n;gLo#a/k-]Zb$c,G ;l6EP6{A 5aRػNNf4HE}8'?n teYOQ; #%fX64-d8lsŌY.[7`ǜ&X6S<V֫k©xɨڢUw`%OSp?^ :WQӬ[*g$rcHDž~>0d{;[ru+4Ch>BIk#t3ri="W{^hF?N&,MR2)Y˂l:>4 Yx$q_ݲeO%g\YxVuw7v3Z\QԾ 8BGn9+ߙ*o4bܣȔR|mjS hcFki|eZ4k' XRīyH(^S0w,ѵŇs 6VP^RԚ"bup[?`9nOiLFyVA?`U*NQW~lù~hf8?Sλ72tOj_I y[J`ί4j^aH DUQh"r1ƭ%;fJδ4 ׋I #.`bnXB@ݚ_jr10Ş[甡4qsʼnaVҝg}$!!abHtJf҆vah>, RΝ,mSN,F'0lX%OXq1$z0jJV'guh<]HYHRW\uطIsZ>EjۆSʼz=^AIk)T,' *y%G# 9R4X;#fI%eU~=mUl PSɳZץ5r޶ BĪb0JITnAN»Xk.jD(?"kbIN:2pwc%nL-~>o0׷DoՄ|`٠mDm3,PDXbsnnY$0 eTf0\F> E6 +"7x /0|r HP_Y$ zUG}$x-t,N?J [䩒^gpAK")C Z@d ]:JMAN|^oH9Q8**O[ E|Kڤڵ8 ar{ VLpjӃ}4JE2H/p{ \&Gun/x"½`끩Mϴ>? ? O"B֞0Bf-޵HUZ&aY[`=CF4/&#ߦB ]pS(Rs6#If$kDM4ݠbM C߱3RUl^@WǁpA0<~v[}~VAO3LBX/g1׬7"ArB@ZmA#`].7G?-;{?O/0AvyxVG9+urX"u=G2StDubuKF^8$^(9r`N=[N:`~s*c>G1Dch~[BtNq+M#? <^{OSV}PgCc NEMHԇ=Q=k9,aM2hAC0ǃpO3b xcELț./\ 3ś8dAQb6_mXD% D5E$r.)i9<Gۤ-29e)~G{)ߨDƲ]jD]v5#%̾wӃF?s[Ékyk閒teeafp7xQ c&$E똠kM{ O|=M$I(K`&74S\  xg9*)DKl;Y\q*CH+TYK6ARCa XTTEs~r# wuZZ9Ĵo^c]ۿ;7=?ǿA1{lbysn~ <"!7ͫe-hsmEjG JZب^涌Y/|p6UQxT. #W[D.@xSѪtXTW5+ .5<{uQ!]P6}}<޴a@]UssYB[:їyՓ9.o? 3*%!˘ɱ5:p5ϊ]kdZ@GrJMԐ{'(0~.kzK|nm?6k:ɂ';`vYDDWuG"xƅpʴiUKk눦`R8VnyBr<̩=1r:k"^ U2 $cE9çu+x͡ 6V5msD#B/V:ߦ A2(!O6~5S0wm<8evJS\Ax bH28̓! >)gqЕB yi󳅕fXj{D ,^Ej ~cf-q*Q}p(wr/2uE>p'${0r'e3$!](UWpR$AiTVGN+e e_D-jdH If0oZШB&dƥ3KЏ;* {zo|nFl%wϪPr#'/y3 r{CBf%Iy*9hc7+Ӱˏ퍗ohQpVv/tP }]_QX'rD<)l̛'_>6J (zHytw^g+4T_yOVP[ݏ`ٷ+@'.48\#fG<)`y0@N]E1]Âƭ^ėȩ]u0)Ⱥ(HeηշJ0@3ϫ[n"HF""yeOєWErz`v~m 'HN E y@LzIVvwWw䌾HR3J뽗E}-EH<1ϒuS4ʭ3ĦN%/jV7cHQC[Bc|KYm^֑֑;?d,Az ?E (5q)&=vy) s@Rj Se.=ꌃY/T7\ۇ~S>1-}fNF!kiRߚ0M:wzkiZ[<8*=C}~ }5UvSu,B̬Co EB r$27@'WCa[2%Eyp`~w}3/|0RΔy~چ:.EVa?zoӬ.4ņi-πqYX۩'_ΐ/b" mگ&b<:x<"kғ]]92@|-YOZ.k=qͨ-homca\&DpjP}_@mʽ7Z$QN-'HpJt-B꣙) ߞ10 -Ǭza-~C,SIզZJAC!mȜ6jƒyYGT?]IЧ P>>}`d^ƈD{px &qTŤa1 }-|gȭQsJHƌ>Ҋ ܝ:*f "&ya(6SBS@06"84Qf`Qzz!K=>^;1zi"R/|L+W%#*'q̔j>f)&QH؈=(M l$+1Y)Ij/gn9oB6e.Ub!!_JGu㐏e}B= Up1C΄_sbf wfOH Ęቫmޚ_x'fam瀤nZ݅79tF9yB 6So3r( #u?hb)>>h2a WyTjE>҆Zbi]EhP]TxEM64תE'"3Ngrkh)S`p#(\z\YXs] ҄)0pg),>0(}}L\PWK.1:9CkyGX [2 B @~LK˾Qv}Fs|{ # 73CNl1pNcLEE#[*mEMfGCl}@~BϞM-%YBs%=.-i`Zuegh{\LxϞ8uu)q `|O=saY#ђp#[o^}I#R'Iǯ K;5S j;#aE`*2,"D&T=_2AĖQ`wjbΠ4ňo,WX fy*r 4Eqxid Bdq)Du1b֪2zoa]ĸ R5[nq߆ #In(< W8US5ó5џ~@~ƌ1߀P7'N5B7EV<=:)y;[ G^ &Y6`4oRL2Zn|kxO& ~o7UgWaPI[JiJJޮ; eN| \`'R}HXd.HCә,˰vc7]ty'8^X#h" Mۂe"V ,y|hDN5r|Ց?FeV 3C2P&֊5H矹,B9VדB1ĬH\.BӋ'j(?rTOy& jXډ0 $Ī}^m} ̍f)u)6|LHFҸ;ޫD> stream xڵeXZ57hq"݊ݥ;݊KVKyf|+WdݺɏPWTa21ۀXyrr6`f)GC+1Rh:y\cǷL{+33%@ڿ9MFn9-@cPqpd02txsf 0-EdfßJ҆Ɩ6. ! (qy346``c PjTĔU j*oUlmm=@TH^U THyUUISRRca hQ1[_ 4掎LL...fN6fVS59\l-o@+_qw?{?I6;Ffw7A8iw86** A`G lh0PMqC_.uaZyx1^ wE dϞTTd߄fy?Deߤ `ee0T l"bcmDAosrwc_Y[m\)lbg&NLj`PJLHjl_Zcfc~-2!y8:N@/:!pL@Ǝo2;*HUx61@1};&6`+7 IM4%de%oh o5'B*@ W"!m ``agdfdۣDYI\{S%|~ۀ?L*"J2t6& `hoo&V˛Mq|K:9zLm('Io`7b0Iq! v[7?do `2d0YLo=ߚqr,8Y|ce oVdmGfD|#kohXu|p|#F 7*֐k;?%Pd9CG{gy=IPnG; ml6R[/@cO_K`)yO*4`Ӧډ DsɁ~|ө ld%yEV/-7&Jw 弉ĄF|:iJgiϤƵFDxڻ~GNb^%떵ºα4[a.au/Mu@:Ɖ4Z8k7* gӅM5OUD/Q;:uhxiUL;_'ڹM5:+|A --_!?U}[ l&,v~Md,5=ʼ7* 5>P.ì0{xn7tI\y>ʨݢY'Ġ JGULHVć1\J_2<Eo enjYK7hz8nD;D9izpS8׸)2 Er'pT=;D ?#@ (݉e9%ͮ&uٔtGM߇Wg17L@iMP1ɩ*Fq~ϗ{6 u 4 R$qrfetE8 !(;y0oAWwha*Kѿ+j܁o(VFao?/mȮϠ`ҚqL9]*u-*8:e ')4`~Tg9 DuDK RD ,Yx~4ڊOމ>|BGOT/5Ց&5j"ad3rK]},Yk2 w>m[o,7Z)s]OZ_Ȋ6KEJcVfYDSEO6۵L2{X Sj~c M&yHMKyOi A/!V$w_ց76T %(Hd㗶{ϥ  +4I<2}WCSdqC{\fWR 3jȻ~!u!;>â2jWGDUiAeˏhFHLiLO}i+oϫpAWv=~0,^=A֊ !snӪcSŜ}xRPmpfI;xgyA K /Ti'Aa™% ɾ:4oK"RX6f[c]Z;CkT'Xoyt`CTM&]a3{ʘ.ᘭeA}:o0yJٝtYc_ޏjD!h%}or;ָ35߲1H oRZ Лzϑ A{iE靴xE @7P P=1,*p 0͖l=z^iѧP>`lV,~BWwy؛O>KRR'N7wۆb"ˉEgi Y]s?"H]lF9:bh'(7a+r}I_lcbTj R#XVT/IQ$Xl N .&QnTny]U_`8pp5YkxNuK*q|آS;BrKM-7dDMe_/Fa<{r{1*qR$1 [9i[ x1Nx">ۖѐ{m\?,8, !7yJ#,5Eߞ?0,';;[-gv!P̾uKօrhPGJ@fƵ;Z62aI\]>9HPO'S`(%Ո ?L5;fcU]w ${IZGrxg:3^@C)'rωJ*>aIL{P! {޻G| HekW5 3%(P8>?w1< ueS5ݟN]+Ul&bU{]R&hP')<ڗ>h*(?PL*e04*ko{ԈAGz\C9$ecRl2aU1d5i="x+LfyG+k'FwA΁ qvtA;mR8Mɸ_6cNExWS̏th˅%GVmY H;͋lX4B/_eMhs9HfC/$Ɠ.ާ?ݨ fwjwW-6厅J]ehEX@V*Skvq S>1njTvףڄjj$&l(*/X`Tk.Or#k0VZ*Hl(S*"秳b?{QqoH.U9c1P<\,6=j|<}V+(bZ U1^/0rщM M65xSqs8&TTU%3f NX\JLdt#vZ4zQ ѽEB$ =i6Xk% ڍܠ`J͑NI.w ن|/̄//@G:0ſol"MYNݐ6&[q}.>~vO߃ N?+q(VyxjPhtZFtl$ im~ɉ7(:.55DJxԡAζ[kP۫ꇐ#F~k> WG dɨWag$O)!Y.1dZB)y˝b`ܾc$!((@ \Mdtcb~}rgGb`J$Uق Œ̒q' Hs}Tg& p^Cn 2#ӡDǙ7z̒}Ī؂ǖHBwȿxp&>!q <ſz@L ^ة#t}KsMk|qΔU\Ѽ͎ z kwu,}TдL=Vƞd1qT/^΍,Ac/Sztq2VSQn;8_)չ9{xt2*hQC B΃V@PuHN}C OoMـ%rЏ۶AdM,k׬4_oqϤX-j1' ޙFpYO~V)0C>{1۪pe&@?R]Wws8Nj"zjg$ux;ov>Z`ԙ8B!Ee:$)8ƹ 9+N* _<b[͉" MgH<mqR+KR 1EJ+F21XVH/Dj`1[G}CsOnagus>df;B=L WSG3`cFR#aO_37O"3ÎdD˵.2ouoS#IYJu?Ӭ{` 2ahT87bu.ūz8dMrɟ=t(:®10A ;WYpY *M΁I2^ z]i5!m9Ѯ.]n-+[3ݹm-8 ng_p3^ĉc;!*SpySW{ݩ,v[*6HzA'2+'xZd_gKh/ݔʔKPj9x3 Ec>l\UG%/7YmbF]-=0>k [c5F \߫GL^2vX]diI|eиBlWC4{F,E1JɣmN/S^.);}/͙,JM]ý(=Uuk(5kUNi +> Bd%I!!9ps .֡X#flgty733\n<)4Ho`Mxh}O :VIv2V oeZK Sŷ$e,wlHɗ}x~;QV88PVܦf~bl CG_ceVUĭU;q MxQ[bqO SzXj͕CH)r0W!2l-^~{RP׉ *JguFyJFC"htEh.^!M;ljQ^`y^v˯t?(,<+QCbSg.L2gfws'3_\m kg*Hp]o#8$Ҟ2,7WVJuJx;o*QLrj,1,"W:b:{24]W2(eJC+3H3A>Gg#V)'{aa%WJu+hs7yÙbTB.+]lVM|^/!2 G8̠[,$nϱƀ,|&tTW)UqSOv=we _^z⅛*)uLo| 1!hVy;zSU  ? FDqޮ1`a \ynnB˖ =OG1xdNZ%9z']Td0I+S 1oHf GdJL6_4FhRXTd>aPԶ'e%C؇zt f NA Mrwϓ7o>'IZzoh:ļ!Es]=C/ #{)CU2(_CfuӍ,y6[stA5%#5 秒Rq KY'@čjayD؎2Cju-s^-c,!-]^<5m֙ Uk_ ǁKPQQAv^,AoKYI,+5uW~t5y2\O<"<@mrU/fﮫaeTp2ĩsJ,rU^EaTibS"1$MZ>BA:X,v.0*3RM =CPkIm3 6K52  _y[+jZ#,9F9=:Lڞ|Ў@}c[-9-aNT¾oAg1 BvRa$.M*3ׁ{xtRk]댁3voԻ ZvrVW>B4ۇvbbPi.5qY Fڶ^ahR V^[k/gƺ@a.y&g?Ni9ͭh@Oj`r6Q/W\w`|!g]ٽX Su-w.q`~҇=s|ok+R3L8JM_z'АWKm/%}T흋[zQ$KO V<c tv5WCw5aŎk>ZtoǾ}@.piB ݄@/u˞ a6ö:jF fb?{iUhtLf_9:&K);}͸iESnxxPRn\'gX)SxXJD=9Ѭ9!Tv*Taဆu|*W*'iI#x=9:bw N9ô='rEpCe|pKg8jsЕr&j/2X)*?k (Md73CmͺY 4w wZ^u=“3#T|9&Rni8¥|a_(GI*䠲lVw 7O>Z.eD}#n93e8RV{4?"og[Wgi!jWHٟ3- %,1$_!̑i<ϽL rgy f^KjCN;ȅ sz6XB%ȥDd\o}]BT&,+~1 +Zj_AvYCsgJi7ȃ^u0HWB*}@W~j)]Wbxy[|s:bM{DϕH?;GO~7/?vȉ'W-xg46Ļy|̆`oeKǏ2m dICL ^1f[mJr#^?3P)C.* (UWooI\LJ{rΨ 7i΂ 7V uYu - A%]pw/Oo|W֓Rd|K;ccZgMUBdWɷXޑԛQd %pPGEw" ׻IRzR'zc*Զ_]-(f.j*^u۶-`x]8 ,5mv3b|0 ,e C>VHXǭGoF)gѡyVx3jhꌲdl 8#q >r {3 ™Be=^zgt9\qX\.M)`ݑxI+`\-YP-Kb6)~'g'l#C&x< 1K·~{UW%Q3•慙y\Y+Bht%k:n,ꛨsˮ2Beh Nʯ6A -ws]-AgXϛwT}~ր1O$9S0Zr^P%*]:pGV̍vܷs͵v䬟+O}XgH 5 آdUt?M-)D?tNs21ڭNW;7O`E|sWU-F;=Zߜ\7P#(2VhŒhbACXJf%j..|k;4vlD#sU Xd 0H[,גrUxB|.Ҟ6.;C t&g0Բi$+}*gPZ0[Ėb?-my߂Wu\#3n!MHrf}\I@Ź]81u+6jB1-EZ<O6WN~]ܯrN0P R"iH:uŋ*hTR-rȵ]X)B|KZ?k, 5HBM'vR> r *@7vK+dwSaaXgc/{f;EKA>ץ9׭HY"7wZ pqXg!,ʄ¾ФH{=ξД50֜4&9[ 0i%UUEZB}] clѝEi%K@nP7󈗗G]JqhܗFP7IoԿ@rEAz҂x2 !Չ.=)٦_5WDIO?"?4~.Np k#M K<Ngtx}`j?'[v _֞{,ZWA-n_aV17w5?%r(hSK\_h1>Ͻ73+Of† ͠>>cl磋nlZM*4ިƿ ru%YXLvN}D5KJ(/=:Bckwd5myAH1 L=k𓀳&{H!eE^8u.j,OiT({zZ@Bqd}nԳ^KIl;a}(>;s$C![\.ɐ+~-{l c)6-V xpo6 4N8.W'|nN}>Ag,zl:DvV٥W1[} ё$QU ccEsƋ;iV^֊[ud[ŀR,^Xi49vB(/ded:7IpZR鴕]l>-?<=j˒)Z{ͮ-:rpWw@"}|GlOјRĤ\O EAςE%NVi˜Y=jCC3yB:'e Hl6sJV9İm2:*ey.=0Z9ffh,`^p<QڗG7/]8@MqkHװ "_X{@D 1l<(F=|%E3 /lNMq2gG)8Kd-rCe|clhj0Ѵ]ǚ޷r+Cj@B.^s̱S>sfʔVG# ϳJ'$B,՞](e4wg6_:{Z ,BY)f'F?$5`b+ +솜^Ū@JE`:&|NMUôif}0rJJYgԁQ1Ky\[1Á3踙So: 1EϾ󫀠&qE{2?7%&G_$NSR-\mmSHМXCUsΥDt~f+ KTg_\!hRPc`yK7#^Y55w1 24Si3^?՜s$;5hZ c9 ArrIA~y Ё\/\v2ψ"#oZNc6k!_%cDw` t"0&5;KFꉼm#Gk).6Z]&Z|1l,^}YTI+J 5' h3!Ә+T셾MiSX,ܚ4hzE05V_Z!Ni:C6/6q<QF߹v=CUrˍ74Ϟ0uiWRK}>+=+]җ㕆js7{LQQ5e#_-]oO>My8V8ՌjʼxdvRȯݛ|m.FXpTr_|^3е+;g@KrP;O(~)u:KXq1'2G2.iĮ-PQy_w'3Nx<Wtkו>|@.Ta[.ϗJ .~,00&sm.)PbOqXqj6{ϧYKG24!i)/MT3ԯtVFuxIٌ&}ƍ j ١&N$GaaE o]㙶<8dU %lSasϯ;Hpv :I FhM O?<ůWd%S!AYUɦΎܒq׋Ny1x…Gw? nX{^RF<kEIb(p1!* Jx--ױ|qbY:)iFMʖpAo0>`o;Uw_UGW۔6%n}]@ i= mX!ǎ Y(IUqG:O4VN{ R}e 6Fgb ?|@~a'T/ݪԥ_;+z<[sKi0<8Ur| ״Zܷv-]6 4n=wueev#ByVؗEC\8Bv+F=taz8c,0I/*F1L*%:4e [˝yR>kftEx%v2,Mؙ},,#Q*} P?M}V}tm- \C5]87jРfO>/3j,IWAIWKwpYg~=C̖LS[kͧllr:5dˇǨ5 {32 1$zT3`*a㾝#Ŋ7ny!>bx{W8 ^ ¼wљ? ơ֤V-ۍ="Rum$N3^ u_jFD;,t2se˖3)B\>< kb.w6c%;IЕDdԴw%j<[h*kA/a]ȭpj)ZwU`$=M8(Sk/2"#t!]{F^orven,1z"*vG& |} x 1uM6Lc@#2k&ю3:M 鳰_''7IAag8(gr֣rO ≻R.6A)d [,2p|8Y _X[7 vi_\Fz'`)+;D%Љ$@o=f8Rl`+8WRĄ6V)y9om endstream endobj 951 0 obj << /Length1 885 /Length2 1678 /Length3 0 /Length 2282 /Filter /FlateDecode >> stream x}Ry<{.leD_B&3`*[4H5c73? 72J!%J$يF,%ZEg,wu{=sssW}#ʌLh ["LÁB9T6B9aP4SW`Db2pD4hl$k.`b}b"7Hb:& Yl3 @ Of2 RtL"& !GD6H4"[)hfA@Ol QϦ D?_ +C #ED?L]@Joj?0Q0J7(d{& [uC=3Z]32DH 00Q uͭrJu$C {"E䈡 0$ auLXPPdx$RU6ߋtr:^v;G] 2LLߵYP0F1h4X}w_jn N0{b x =@˃`0H{$Ee\V냹Qƽ!RsG䂟>gH|LԄ?7ak;!'[ LB %C:v8Ŀ p#V/dzn6hW$͒\džMAjo!9pG*d'cx8k $ I %]jծ7n9;LGZ-醯/C(,."ʲ[$$J;^pg·W X16i}1a[n7?rj1_4gϙu̪MrMՕ`WBg=V=g!S]`CX%qW^TfN^kF,55KM>./eS C\ SKBR%-5xW)GN=xFm#ƱlEyg3R~.] -*z@N8/<&[~i΍jb+`J+q۽xkCsI=O׏Nn*{|i$3,ZD~b8{6h6n^_z+rEz#d.rl^~kla,v1eH\D^SShM2E,\xQTGEM6ߍKU Tܺ^<*|^: 1IQ*T ѣ2a͓ru pYBqt\ULԯ5Ài]MGY7c=v-c:-;_7~> stream xڭweT]ے5pp-{ݝ܂ǽ_cWUYjZ{lJRe5sS+ #3/@dgfb/ `k0r PR9M\A&@^ 4Xxxx(b^ K+W ?-Ldixq:8]? Հ@`ĔudR)=fj 2ȃ̀.@3 9\?D\&Gc t|@.Kg{׏:@fn[8M#b rt|dUOW+׿r>Hs3Ju5ٻ\2A.&^?Aps[=hiln tq;ߪ7qt{Q`D`aidנ[8Xa7wsO;Q534$Lm@ &E׏ʌ> [_5ozZVcq>n<;5z D "R032ry͕AfV ۏmװ7:ۂZF ǿԭ@f65o_7o& u]M9MRPUԡ`_0DE< ,\l6fa ϵ3Q43ߥϕH؛95'j&_fn}?JCzVBev@:֫T;t 4~ el}kZ8v|ݓƶܕ <'%)@EEdX~}1/ ɬ=jXC4 wqO@^IqgVSm U#C]W={t9q|&8~)Ǥɮ^^=yB'Hzak()E mF5͋ɲN0pKh o7yUN?2 "͸Oj4@I#s/an1i>NgϚFRCZ [?M!@kZU<J n<:{YOÄWIDٕrJ ͋~Ж./96K8-7kY2pd . xT;viE8"Q@Zt)KHPt@nMq@$fe7#tb+Ͼ 1Ot~]k"bkٞwCĚ0[y$@P FiX#4\nax/ ECp5DTzTh!TN pvJ3xTgiw&_;ù #T3܆.B($/3)< nXهFBy7x56 S>%`$h.2]決k cލ&[*1bL0[Rg ؋B =}ϴ2<}'19׏oac~[Ӣ8?/NF@Pb gdͬvѳR=5n T H'hڗb<$>cMk9N4=_.rKJմ~c#)%Z\z'3MIՓS+kZ~uߐ$Euw}7sGD#ܱ:+Ͱ'Ce|MQ▣v])/ss( GEb`zYobs@ yg zVuL< Pnޡ!Trl(&g%5vXdB? @~NA,t_00%?ӢMƭUSAhj,I@Bx>2&swz 0٘0m9^Y ;!I =&>#IoΝ!&DED4 pAUi6Pt>vڽ]NYj!dVXd-ˌIG #B4ʣ8L\i{U6Q۵Tҁy٤*Խ:oјPr^M7:ܨ5G ,5j0PLl̔r,%3rOϫfy^Ң`j!iRߊǮ9%*Gޠ.5㢴yrkTaB"d*ytAПF%8/읰]SǑh|tj!\½ߗ4m܏/!4㱄ߢ~wF] ?Dҷ3!f:ܝ EL'g,_nr+U.Шp2q Uye~ķ#ޑTUܭݑL4~B{ƞ7*7eN9v:; $^Gо|vñ=i|l+yC)kO?p8?S(xqg\@>~ J]2]GqZnh^&8~}oNCj/mU.7s9Q RcPj7cҬSL * |~â MEB&׸|M¬`bf%K|B0^mAcc(ڲʳVfs)v%J4L!ztV˵')xQ=DxȈMazC+t,Rҡڑ{ )UܕŭWA54.uKRuX[yș± qc^bʃTyfpReIdYID:񵏅|t8Br+ֿ bs8COzasQs»< nK1=2i&S2z'#(8S]ק:}g1a@s2s_"a3xH5`zvm m9aJ41cbFidY!yCu7 ;FOlzF>5ׅWOrybvp̣b]A >x|Ԑ~xmIk0vh #۞WRCras [pszE{kU&>YOn!EmXr!OځUE>+`%e75yY|f;q##)'{_|T0ʸZjR(pp=9zpLĽ,Ȱ7`|6ϊ`Jveh+9ާP)d5& !\attw-MZuDV1\fY'}Rɹ׆:|}n.@(5bGkpyPb8NU XeK0rK~7"JgN P֪ٕBQJp:F}z]xS ) 1NJ\Ex$ӎ q̋J !V_F@'& !<:dTqUX힩ZSBH,4H%UgK$SILmReڥyD OA)G2݄*&}r9/h~k$ HdH\%!9Ռ7Al+|uglU7[ p0Ny'n;|ьY25!WAL'GXl?uʮNm藮FZۅYfU]jǺpU'T\/(ot)rz(ڄ@—'2A(,Yy۵}rje fHem)\mI i_:_,,AUr+Ɏ џXG1Ec京!k`+l^cjZ緺_DKe/aU MN]7J:3 Wķ%Yڨu|j/r+XB!_($  YVDe?'z<DtƐdauęwRE2q4ʒb ϯ8|}3ƵSi =y#KE0&YHpD<*%:g%[ѸON:DKs2:4/n1DM;'˽RO"Nut_s?6P*X#O('WhpՁ7><$$FMy" wN "?1vOA:C#x?Mbxj@`{Cmu~ȋ#gL50;9OtNg6kT::frYː ]eЅ`v'+i;nӮoC̱Cop_8c[pf}\-h3ڄ^ygCwe1xKv'~gư1efU?Doe!=3h<z/%6]:>1&& it||^MSs3dIk;.OݢW*{ydplQ%\RhnRZxM6v ^"]J}f1qN`hF}%ӮvK]/,x#ahy3jk kӃ },abSlJ¯ LFkW Pe*b&7\^^z$fIKo㓎;X6O<,ɘ9aDփc}X @_a*J\5'P̵um^OȬsL1}Z;Lؿܟ8y, IÖ] H.g=Rq=+4qDbx- b(3,̸I_Lx oúٳ'4;_ݮOP1K/0- 㯯}Co|.N_Dd@'*o+Tb7{:}UjʁEZ]ODoivwR%koF)W%FXZVqY Yƻ[$^ 19NZKkES{., 3GB~f5E .@vYI($.](w|sL=eznTLƃkGfm RX@`9cOۆo*՘y7 RVJ~ue1-Oh7Y'Ns3*qDhYd_S$MH𝁚968<[Ҽ-!7|t,fhz̓:RhAzAXX%ٌ{]~ŭ/BRI wC~^.޳QJÉEy5/gO7>+1H^6"/nSG)^ޱ#J~ZYC!`U?ۥx|@]$ zR~9/.U.`JˀGeq̗>)n}%*Y/HC܅aSA ̝h \ 5vC<^9=P*6(Y)p%A֘ NR.g!3ZT>躁Of 웄WL>j|f=ZQA~J@04d{=k&bܬuLIu+Q7#5^a`FN/FH<\˯fGY_DXě/yuЄxaEpNqm>ul _t)[~yQY@УUQ_^׷E ;³Yrý0df5S#- ̞F{cF0GSH,]s&c1] &|;G9,i-+[g2[*5)θ'crmtD{}ru)?=%WjM-],W<+{ ǭ\{o|4dr)q݄Zvc @ x !ԍΘ %| 宵ɭ9 Hrq4޻eW{xJ̑|(pNz.NT,' v`+䥤"6"L2YK3}@/1IÐUR>^LD`* U񴪇R3(rZeyDAq?즖(+LD eV;ap2{y s[o(dUJ9 1q3 w)ڛޙ;UYۺ?Kͬf12,\͒tIia,TIT8{„H 5##oO u҄Z) (Dhg2.#!i.JcCB"zX"~\Õ'(JS2Ф0»<MSAȭhs,Z{UAS?WKADSiK'nܠ)rY6Ã|PSv hAM.`эv z**yetm1˷/L,ħS-h^&?MKޫ^؎Y1?FoZ:σǜ~Kqni*U<RhQ4Y$ < H KnYУ={YCk} ٸ١zA;xI >@NF5#Gn$O1G SepQ:Zgc$LCx쒑+KU.nC҈&21vwa5^Mݱh:9F6 IAN0 Rh_af>Zf ޢ(IgiHl.Uѩbg ֞P"AjY#)ĆmW|2s"Ĕp +Kٖfѹ@U=-\{[ ڊ+b޹:X- Cl+eDDM*vMr G-\p*hrGi~6j$-h kuYgA&R;(ؑ pɧ_#DJN$,a]MoԐEl ƽȷ#19&\\ %wGbraw#f|3Y4g{{s~FܘOTB¿2u3xN}Ѻg]^(\Wt*JF(K(JTk&WhL6 'Qo$l+-e )+[@j08m5u@'oX;a&~MN%qL/)(H2w,d%irY3$8Lh13|eLq:My(nϠӎzXeGqy_Q7ڸ=')R =ZfPR'㏺S2`8_f/c ->ր}6?W6k4w"~3{(lu'lt<ގHیѪ 8@/*\?:RZue8fCBͰn[uXQKk7Zpx{D/kvUH^O Shk`ٚ./%0)o/4BY N\Dϖx 2"7ON_$`AbWBa6 * s5f|D{*D!aIFR ܪ?_(+Vaf}Kdi2 AWdr]޽}.ăj7Bek5o]ڄ]K:L~B*q^Iy~s4b@M0j>ƭA£Yg^A rY唀.9ȓ+SjQ*a%}4\vY~m9Gg3Gzq }ZRȒ[ϟl!f_;uʿqAn$$i9/ϬeiԘ,Ƴu!%9>-^C4}=aG A -uSFwOT >>,"as8:iW^9!\$(j{$y&g (N l :n H6EZݟ+¨zJ9%ebkAOnx*ˀ]7,Ǵ܎P@V~:҂J0b4` *69u*GEn&eAF#LqUYG"9C!ZxhAd-*N Y2d5})g([;MPCrRq ul*`WzLi$nӜP;%9rÙ#$D󈝸nH/8+_v24Qf#B 7 D?iT.^)'XesSq=8DRgْQ(փa& CեS1kc'rP GUֹ[)$'ΤP @dDl3︠:0;ۯ${AڨBLJ0L[a8TMzt8e-6{ 3Gu9M~=fmYŃxn ".>S="ITy'd;.OH\ 17BKnni~F{hesuK0ƒ`r;p?luގd5ŔFF]L6G̀=Ȏ6 p\P9:CKL0 j AM NȳŞoDDX< ^~)V=Fegsu;!zTtX9pdwό sN a86gZCkc? BױXH2 8bYۘ$p = ]=2eB@\ j ;$ Q.oWwP3=LR{fT^3gf\ꬢ5Gr2wÁwOEdN,zK=> stream xڭteX]-kݝNph-!8www .A/7wΜgu~]jڛTYQ(eoPٚ:)0ۘɺ>NJJq' N$66+///%@ daPբg/?Hg hc` s_K d+)*Jh5@;Gʮ&6 Sh ;lqۙj͙K` pv>€@  9,\>fbٙڸU?Rhw*3DH?"ߩ\mlm? q(zg=4 'd??E,>adecb,)\L-6ۮagt?D{A[L>kʙ>KkOOߞ+Ҵ>ۛ/11{WFVnn#; /?_.N   +F쯥Qs13س2:9}h7",7JHwa v(WWe[nR09+G7҃cCݝ<#!G_j `6(FN?ъz1Ţ5jPC4w@GEq4. *z`txh w>;[1im;c_Vb$i ӟj  =Q"s4AӦosئj]1:GF;_0 LJ:tŤ~jrkFrq O=iR, ~iޗ\i+X`Vx4 ,E%r Qܛ`PTp]C'aOM1VpSЌ;y|$rN6^nޣh OZm柽u!oJd魞aEQAޔ6"y aF #:z4% 3CNV瘣hk]罴v@rϾ"3j㧷o44/V-"aD3d^Εbjn˔7hD#HZ<K[2,d#]GԹ8sL|Z(uEQ/EzKQ~E۰u* “'m{靦p`F*k8!Uh)sދ^M:g69j_w+[d9∂tT)@Z&޼Ϭo~qrQV/ :mUJPnYslrC-Vx+#1B#hm bΫ7Y[ Ҧ>̾xyS#ԬBVo|qZSАكgxI`yCVxQTqK@) PrGLSaCp_c(Ё0X$gɊyn)!bwEW߈.YaR'ѨDOٯZc Xg9Y ]!`WкeE9p}S{@Y2k3lF ]=9 WuP䋐Vf,)U㑋0i_WSgo)*YfTȡoz;Y0}$^eΙlIsQeC_k@ JWnuLUȇdP~eh%lW 8Uq$Ue\r<I9VĦ:X鎉\᷵HyFO6ҭk٫9ͬI zCŽ?sjO!AlɅC=_ǏXZ7oO ײȚH*|d-~wԜZS #ڊ#kp%ΓiRwyMbFrHy^K *P'$2TDUMLcp[*}YhC}#j;Z]uJoG"CՈF !IQh|sL׿o9Z}g @)>juB.̛% 6 _AB sko/ͫC=3(GE>U9M.=k`<7 =5SIknnPOSeӀP\X#rŦ|V"ﵥi"#,~kzMm)вD= }>.RYҐ(٣q=!GׅJhc++(#²eigvvŸcO jFHo '`Ş|q\$u*\Xmٝ3¥|9Pxg(e*6}]ї kM%_a Y:͎}X4 P@WbJg{ːGh6"$,oሖ܈zNJ.5:}wo! zӀu ̆yQ/Ҏ&h1N;:.~kބ<;VVWaq UcL˫o{ цX6 #^xs'G4MROPs@ڣxnzycb _ Da%]+ݾEĨHBЫ&XcN ȢKt=^Ft7MB$-Z^ϋJY(V{~ Qg^!@"7̀Zu5HNp(Rj-*C$x{䟶V ;1WDG6(~:F{m'Z/ᇽRŝ>6p{T+ކ*XL>v$ȭ' V2Onq$|J8  I0^݃^nu_NzWɃ c)s^U6^dHGhU} |=WC'ƅcjJxε/ir,gARr-۵+mRkp{M7ij atwTF6&6uT Ä՗eDI; >p§mNPҰg}"J^qOk%eOcEր M4$C,DҦy˛Ni27A`Uarn]caNwv2l.*љ_Ϧ:-_!ά",6(nxF!RJlůN."_>eaJh6zGG0e62_U?&,Rvā.!/r\RSQUw_Ly~m8W7\wH ՚ Rl>!0X _O3T9(dڜW u @,?QznOiٷ6Ӗ)SBZpn7sR `ص$1g(\|0_Oe-$ Sy ^7{]jSVDρiX_9d^eĴU(@+14;"hOHͱ`*t7d̀lz!r2z{x/j_]1.Y}Rl>% 2z0>$\HhjTWX\lϛ |r4QD pG\QdF3K~HRy.gS.ӶUH 䔪>9K{~L&;퐣>e"?bvfeb%xc.~dy0%05qbE4x>XZ)g`&R)-*n׀͙s)C:-}WN˅:|_c$y&[=a]7o|>LzuPpcږes&Ni8Q\zcRG^55OBGmiu6';^ ްKa U*G#5c^7 C;5W9\~Z3\oj+jt.Zl)\.0{ZC,w OOBed8bv.-[خJvhJXZ3+WL5b޸N\2nvEŝΟ[$\JmnzI߶y4_d+ @ C62,|"$[ZEpP'Ab8xxA{ΒӒ*! Cwy5L 5u]FPWI; *2G%LQ&TPpE*BL;< 2ayE NZHUᛎεWxzusq2ŸVp7V?B5*"=]5hkM!n))(އt#:2ce/nJNA@VgFժp7%עSͽYGc_!Xݡ?rȊ]}d4fL_-p8HɅo}l {0!̻ih@guyՒV0M[t2\5t̘j5o8dT޼SzKh-GP t ۳Zf\CiMA53"B>hz4]Gq(rK1!b|qd6ezαڃ0~cp*DLBK0^rUgH`SbPqQ?z0w_& k;.;wr##S6Vvaa(qZGBwX]7|jkVF lB}N'Y1Ş~:{ ?4C?j$1.n(e,.fٌaޓ\B QԳC}M%u j:OqP@#*}NfpedD׻I Q>M٬&h <,/\T`[LAN m5Ys_M n[QwxuĠT8%^][˺]3!c˴L;̰O8o~~?B_ɲ &%qgӊmoBdmV>Jw6egxgbA V]:u1ɪWmLB5> O>lߟHDM&c 9ю^Vz+.'iՈhnj!Z0ӌ.i)*kNJQ~R_"lmw@ C%dXyP([9m搫ʧRQ]/`;2. |)Z_AЖ5enr~濐J{#ˡ3ʚ(rXn9<$|-QtU^*7ݳ 9@Kl7SvDb/y$L bߞ~2ʫ^UE MuGڡ!S6Q\pb>#ߏwi'HRW#Ն{#m6X,BZV> M` UVstXo%SwM=}x;~)M)#Qڻ)xâsoI n( @)JhMq5bb̸)wD1iO XlM!a4it4FA34wLد=Zz^-hQdz|d 2c"A0JʐacҧVKtw /Bހ߹ #J^Ӛ*T\@# x3GB{l b.YתNAml22tz,r5 5.'X!!.K`>fڽ2(.) e;`GN/:Yhx,8f h{N9d8]Ӏ̕ H'LGbȉ]|L17xFBOaMsVWl"l(\t/?WH<^lle=) ).2|sV @W0D=ͅ~p6x&`bh"9^.06A@lua?qGj;."F gbR ƚE$)!<rm;Qc2T,S"%9@A~Dn k)؇@ѕE0ik?O!meVYłbZg;]R|1%v 3~) > a1t05r,T"_rZffߞoup 6oNil"TgePжϒkĤ{WOHO1(J60{ I{^V) 8# ӭr̾Y<%&9V;AݣKNHM'ps^i J\#>o_e=N`Z#mlցq,];OaIψ c gݯ/uCiS3T3:|gp"-WB"[ɾ1G ݰ@Ƃ/b_CRv@0Yĝ h2l(d`[%*kȲ%޽qh1!pR5+ě"ZRG %]sB3wu:-:k0%?f}62KG(miZж`>!4դ]+B9}ʰFL~Mg1sQh=,$x&*D2qQpO:Ow))ںt[c޷Ř"VЭ)kH/Q=/=a vDߐl,wc:1e=_!./ީؚO7aԟӞ" ?r"?+\Z9+Ǩ}uC$-C%+wuybQQ}iOG߰(da~`N\_?nDc^S84/#QBZ6B40Ű V脏ޭ#+#;t wSreY/+͔ՖKX׀^4Z'! JRR[+$ `wYTWz` F*VȊM8ݼSi̽_:Q;HL"b/sb\Σ0ƥ:=!Z1>b'jéh.~*N)Dr1(\ņGf:K'dljfM7tO踕D)=A.$o)H\ 6_pek2DtU҄g/N+ռٟFJ~2ɎLw&_Uv#b|ԥ =JP\= (TDad%7/+Eakr$$ =]RY0} LOG oJ# !,B]Iy4 ݶivci1Zub].5RQɆwSA/~oO+ָxg,0ձjl:u[b;"a n-J?!$GTO~6Έ'm ;DDHߊ ?LL <0?6FSjnI?~\+]13ƂF^ik1moRB:)}jtD܏jjh_&UR%RK9 %@%RK9,mo|KJg%++8cŌqc@̌No(tb3pXT'&@> stream xuwUX\[-,8][(p nݝNwo=9eh(TԘ &@i3; @ lcfl3 xQihN_ b+iʫ[8lv66>n5?! t:Xm_)I I 4 t8;毕wV pi|֢gdd70q':Aׅ bWW -hbU̍N pr`e37b,,@'VBl$ 6 853I)w-`s-9۱j؂흁r7B7:88@{ԂvI`c[3oO; 6P=]'gK*;; l0^0{Ec'@녚Aldl(h(*1gJ2r9_*[ۿٚC(ub,B߆O%%Iq3qk玀Oz6vpcr?GGl*f ט`7 akT8f[MlښGJ)[SPszٿhSg}Ag7MQf!5UbĮ;c=</\Qְ[,o2$U-D*`cx]XqȆaR@?E8c!$Hڗp=(֡V BJsQf+Z NKY$w4L}EksSކm43+;,TsjBS+>qoѦ)?4:"8ܟlLSgrz&lM*])W=3P8BY\mk_#p[zR5gmW~Ht+llT!Q%T~ p4xɩvĴpY }+b32Ij'L*׽sD[Қ1RΌ" }L&eCVff3!Lm5Wpf A &BۗǺT;MLh/W?b#T<+*N#K"da%8Okε76"!vL+j @5]H%<֢ 0#'5߆bV}k2DGX]ēWg:j,Tl9l3L1*)# ⭜Byx?ޘ2$ʇBƝW\ Qozb( ` O=+-WqOY:`l7S %L..'n*cN&7c:4ۄc#z:_u Fp ǵ=?Z$NW aG#rk)ndPo8S6QmJ~xOE ]]"|Vva&}(dQi&YwN!?]5g- BOcGl={B}R_50K1MYѕxer Uxf^ÈUK%\4$K#@`?*^j(!&]0ř%.e'[S 1ALZ}vj)ԉ`p790~7o\ũ0—;⹕zSs}{a>sMJipѥ۳2.Gx+{Ц1N&v!լ8xÐW;\b=R%s)iBO=Y O|<1#%o#n:(_Ϝp˖ R !BIDp.q蘽 n?mR ;\+[ߏ9^sm?ǢAg+m8ƽض!ض)s/7Xu#nP#ddtP)0M^ua0oϴwgOPQ04t9 P 545ԭa4vaZf(Md8pr(,>vɾIf|16_w11OYZ2 "mޟëT 懌jAkVŸlSw¹~F50HT+(y9R4"jX֑G0=eUh]}@\yfЙO H韐7/4HL{&Ǚ$SwQݗ+׃&Gwr76՘);f1ɜy^}wQ)EϊEᾝƚCY07KF.]dqV@ Cև؏R;{M k8lwԼPb;~9ʃAyLotW2FyڊG WUiЖ.A)R/uT=Эrvy]lV\(O(SBYK|<,2MF7pV7)("vC-DuvJz7v4H^[[\vYc"hgl0{LKĥN|BY+)BUs/I/:%T He^C";ŭ\a*T\oQD$~+Osjh6uw/-w:8 Ox9SG- 򩒩;8CÉA# bZ--`O ;~|Zd_;;8./_Nٜe1HH?Avԍa ?5YMN@ht<$8jb7roR~lHёû9.dy1$hET.0'fD–Sx֟a>8Es1<J3[z@{7Ʋ lron!vx샨`RJr7ڐ7RGbO*v((쾊T֋(6ͱlW` 25i[*8AlzFG+WB ctА8%% ˩|2j?w.INY&ZO 9z[,e-zt* \'VU~x)՟u +Y܋54M^,Ϛ9[]ZOC.L+$L2W Uyruœә$Q)ɖmԳ328 {N\4qB^* kJM_rξ\I #Z^bDɲz8{E->URwuMC+ݲ(.?YMC߶@]-e0xKx -YsXi/V$Ʃ6aQ}@v%d7{ӄ1b_3ݜ mo@88b6=|nPM |LyiÙ?ρ^YrgaUObqf8<+aYB&]JSqa*OsAbl/>v0L\~Fm8T$YL;hykܦ()f69 sJ|U@`ҳT^9щS@A^ʅa 3;9Sg)4iߢ:&ht.gGwɥ|tc'jNH҂0,~:`o$ou9TV_Piޱy۔\a7fpqL%0Wː5"yEʠ$@` @M"3ԙ@fg+4 J7m?ʟVW?YW0,z_Vkp{ i1dqfIy1د 0Z"DGkC@ŏ(LguQLcC#O 1a4y\W]F/K |4s'Ts^u,Ucu⏹#aG=l Ϙ9Lގ$9,k&G'lqRR?Y19c,'86U򛢹&_5{C9V7:}wcJ7ǦGZ'P(;^Ιǥe}moUZAgBz1M?sz6^TaI"|F21,K|#`dwt^"%5l7<ߓ@^Kߤ0ks[m:AgbX MO@j&WQ,[qs}p [p=L=Zu,'dЋDaCnZL&WVg'8c_E>I"?Hp~0Qws`kO6fODlt 4aSm]/IkK\?$-Wo7#%h>~]2^/P\sÏBN}^}lϠ>ii ZySXȨf35*&_Od1gE$*e0.=v~֒r%#X$*H0ׇ cMb e-~n_Nc5!XG8xL({o:יOFF[]]\LhՊYY)Ss`sPvb3`|A ׵\q_F~,#gֳ2Q׽OP~rfCЯ2\׳9z5K?˯6qqF ~.c{'.uq'\bҠ;GsNC^6`e+'oLï\n@k46=Zlz_9? ۧ%+>{y1BEW+ZΆ3_:`j!h! 23h4D+m8s_$߫ԛ}*T̸aF ]䞢G*dCp1 Ɏ !^fO(uRIZ @G] lS 5*1@%VAlӆZbūjT#ͣfoh}D{NG|u8чo;tqMV\ w`"I: !-_5FH}Ch3Y UcYcqR9ZͯiWQ(ta<%\%?o0%<L-\³Xtw+аj:$l [)GM2{3{F$yj>k88o̢ీcp^%R:1>- m=Y ȸS,@e=B1iQ*]DϹC[-v{޿#Yale%\!}&IH.F.Pf)rJӊ4@cB^9K{'4Pq^6 EQrm'-XGRE/QfCNLΒ];>-(!vc}`#/\r \ =jק?:^i|3kwkSQ1 r7"[b>,J Ij^s-m4j>hy@s 鷥zt+QS]!^HȽR;t5\|y'߇,㟾wf;ty9 I@/N4tc;L; ӗ.dڜ, -L^Kb+3].gIR ~z&E@=A|gqBxN+OxY8ܩ)b9Cl4,;B5싾o8ШTbym׮gU!.ҺhEUa=DU7`!~2Ip]0^jziQ$4~amFꋦycGZ:Y4@1S~Ay~&{JЗ+pH-)թDЙ;!30ՠ#c$Ԟ EcNѰgŌ∳B];Aq(y*t?PBNO;=/9OZN)7lf }M]DV- ٶ6>[a~ DTat5Ͱ_R+Nb̚wֵ$NeWsY̧"ІMXjsyqHTlNeq2eQ9_bB ޲p>V%5Aϩ1dѾhM0l=.M./M Bâ8hCGIznRJ)ET< /=oLdEdS+d(py.:~oWp=d (}ez0Uڂ% R0ssMT*W4[ׄߴ:}&IGK7\ry1f7Qv!NK>㕔أP!ęi`Diۊw/@dz*RVB/sX*bVЍs@A:67m:ԓᾌnSYZyVliUP )4GM_#(L%K}B5SA\-?_(Df[ YL.Z8mp"ݜndk %O:Kit.5PV-i1jwϺBYG)N _rK?KUjatz<.?_ )3 ~xՖk.$H"\mkz8A'RjljLRTYz[y}G?ֹD endstream endobj 896 0 obj << /Type /ObjStm /N 100 /First 929 /Length 4679 /Filter /FlateDecode >> stream x\ko8_!| x' $-&$NgqSJ}vן(YRlq$Q^IYQ$Y8DWhIWX\P腲r=%E3ighf ,(KyNh$"ShwCDi£GxsX'Dc2j x"hH%]tbGA&w(hH&2 B`4s!ySYz^?,֞ >1Fcpc*n4*Qv;)fŠ//]iY?f>ǭamj%甂c s &q:svZL#ooeSƅmTtj)qQLYm̆6eSCi%(%SJ3j kRNyhB.>%䧶vr;H@pYH/V@'1pkoVЅo9#qWoΫ= +*GY=$F pHw\hnyQ_ bBz-$m>,w*,hN},im28ZYζ|JZTY8Vlf"Mt}JBir"tF ۨ@ M{VĢv5X?w3n:lJ@G]/Y]k `ȰbJ ִjWNf)hPӶܴ$?#5qvrz3B *S!{ATCmVnx (ڄa CFJG羣C4xyc3 D#*ǂɻӗ/wڿOfdtg]5MTr/D;B*ڵߝռ/ H`w|5ʓNf; 1=>vB-qA[?]Ǟ7-;f>A1*,4gr9g|®5lnؘMؔMM_،ͮ'yf,؜}fd'ŏ4c5|O=y݀︸W#~Ѵ_Ϸ3+sr |){_1`!;St0ΆhjM_QR\AQ(CG[&y>Ƶxn(I ~O>͋Y~q> euS6wr 01(&yP/O%joNu`d{b{U]B&NG 'ACTjO_M'_M>3ʧӭ"Xih>fX29UX[E,odUj[wmŽN~߰u6g!762} GDW5F k~NjÃ?ghav_VJswx,9ff-Gp&>n,,Z[Sj~;ݫ7)buK"+)MYڙhD5Kb_L6nո)k)V{g͇| …vjO$ v x k {'/^ \%KȲ2Fn+.fo,,ǖ>\GX7* xkƚ̾ lళ 6WL|l3mxxNKܳ~D(}MMQF _&ί䚸 `00c5Cbx)|Ke$j O]+)@~jo… *p YqcJgAnJ2:m#* aĄ:1Rm,  QݐfRsd%%j6Z&&d0e2@rB2H mhlme$ʮۅ+w Ӹ5H_66שi^RSi6jp2QH~^̮ж~!Ҁ;]T3eQQq&cpzO˚&e5`M>k+]q(Zu8JcpL1yW\|C˘F .|wTV9pVuG[`i.kyW(n&x!mƢ+ʕxWXh0&dFմf ZMk_UXЪ{Gޢ-y%JlZƗ\-rZeo _Wŷ- 6K݊S:CDG Q˦+b~]oX&kiİ/he-eB df--բU+h: endstream endobj 963 0 obj << /Type /ObjStm /N 100 /First 859 /Length 1710 /Filter /FlateDecode >> stream x}$5 hbq X!/bHa@<>']k^}qϩj)MJٔ:ulu>x} t!UyS{:6QUm(nר SP"ޮR65y"OHʌ`E `eu";VaeFO\ :AW\<苹1~XJڤmXu"q#xJFHLUSKU6#mABS! VAp/"]K]@sIvۚ Lt@oB<&O6k,mDp E. :uwK cH<uAHsklSs40aw]{)3>  (.:jş5= \KM븱gGMt1cݓ *Vsu l}dZ]VTW7]R-vZ%Ҳ)ix:Zj cuh+':@:wY;I۱j3iI-4B)iBXDS-7Dl&©$h7ўF5u;;*qL6gr%{[)]5S-7.LL8 LHR-wptѦvqWEW@1%e_{؛ גw|VyӺtKmyJؗiUxeVqyahuՉ_WU~\Q'܌ʲ,͊fկcȊ٬oV|rVeV7+kDf|3%pVy2-iE03` ̀sdl̒w̑0K0Gf\SΎ9c6;暲Dhٱ{]攽]lvSv9]6eJ;vl)el#e]7ՑѲ->K>]U>dqO)|3˞sΨr@߬v&j;NiNZ-jUEVJWʛ)ޜVľ}wc){u{^ձ{5oFط}s5bߌ}K7ǾE웱8-b/^Rط{IW^"bv5ڵ?b]OѽW {f m&gr&[Y!phl3`Jȍ F@=rhdIO']2}~1%^vRIOGDlg9-ENkF;e#5 mgZYGBjf=a52TӞ vfyY&F6j. bgjعgd-A3M͖ vY9$]Fnif)1}e@լ.;N;~V/vt1Ȳ't#5\i!}jwʒSXs݆D7z|O>L'2Qd/TB{FRo}i7?x?v endstream endobj 1002 0 obj << /Author()/Title()/Subject()/Creator(LaTeX with hyperref package)/Producer(pdfTeX-1.40.17)/Keywords() /CreationDate (D:20171003062237-05'00') /ModDate (D:20171003062237-05'00') /Trapped /False /PTEX.Fullbanner (This is pdfTeX, Version 3.14159265-2.6-1.40.17 (TeX Live 2016/Debian) kpathsea version 6.2.2) >> endobj 965 0 obj << /Type /ObjStm /N 37 /First 326 /Length 1533 /Filter /FlateDecode >> stream xڝYˎ7+xl0 !@HSV֫EV>ř8n6YU|p Nɸ2r$e1!E)$W gk {qV*s&|y8_u}a 4&dK%26bkbn,r 륖%< X\kjEZ^riy;/%tz!bxˬS|;^)4bXRz@ږ(<%(H)1VBvJnRle f1Ang:Aux6 Ia’ŠK> D߂Y!'(L5ܶ0.$t8UZ@z9ޟNOuS,2>Ӧ0DsbD0alB(+p âj675UL8~@E =pܜ{$y9M[i$~YIeV!@Q ꗎ]x߱KC' َ]‚5u6Ÿz H.sr,uq,U>W5:TgK080Pw D`WU|1kB%x9ݍG|\Gݏ= p 2V "+ e|}^a_aXg\ !oQ@$$"]"(DBh"c"k ]]%nYW+xq`864 YuSE9t 'i8G* "ݍ1TP=I*aMN93 71g0{a=I yLNX.zЦC?~[zZM )DOzc=ܩ˽t۝Z2>T2<\To@gwΪwآ?0B7O2s_E*}W#)Hm\H[}\}jNJUbH¨j>Fs"R9}?x2!).VZ]֣Cͫn;naW;^-`Y':A\٬Jx @ܣԣJ[URaJ*70ӂ8>>_/YuUzn8tw]>֚뻐N"lzDB.w L]Ej"t= 32jү>7ˋfOi %ݸ%nMq/KC96 _2磹p><>~!:.Z`BU#ӧ/ǩ=M endstream endobj 1003 0 obj << /Type /XRef /Index [0 1004] /Size 1004 /W [1 3 1] /Root 1001 0 R /Info 1002 0 R /ID [<9E55C9A2D1B4620F541163C77E1CB6BB> <9E55C9A2D1B4620F541163C77E1CB6BB>] /Length 2339 /Filter /FlateDecode >> stream xKh^[{4m&M$m4M6MN&irim6m>PEpA'vpAp@JND,Z_{sRV.b)˪eYcVJlM;|f@ khE{GЖ^B뀣h9p!>8= 4m6vўChv=g3hOmYN968vm \@A{.]C{ .mB/=hh+UAuh/p mm \GC{nBohB!4: ݇͠chV<2tB[@ˡ-{hKP̠-Bohhwh|:̣=AF/JKЎ݅ꁖ1NBNѴZf2` M?KmEOΡiI44h))An8G+9(H9(Giv4kG=>EӬ)B=2RNsU8͕G>%%J%5>̠/jao%ewi/̀2Pa Z@ x Bcg>`nAO PveϡM3` mD` 0^!{vj=ytnpW^\M`a`ƀq`i60 s<%  вϸ0ܯP{"ɛ'$^˴&xlۀYY&/eXh^4H0ʧe@E ^*Uz@$,6̀a  9 8N?nU˚"EK}-kMt|=,h_9u+(Y+u6?}I \-\w-lԞ|2N7Ԟ1fY~R7hn^߷nrLN_4khk X6`mڀk X6`mteг<=e1jy`B[VK98lc=i7u&"Ziлǝg˲U u}iAPGWݟu*Ö"#BPVM ee_ `rڰ`^p&Lzʰy%DK2zHKz5Q w۲/Ue3vƨWgߢ4Oؓ-{}i:愡IOͭf?e tXV7aO" iL1Q" gV$+ƄQ4&ҘHc"4&,Kd+QcQ'0%͙hž_lv?[ºY)ezЫ:Y纋I˒>iωtƗNv;՘er1 PWVyUSVWu5mWtu*}+,tjOᷭ0"j;]1k_0\\^T  i}P T΂hR (8& (HJ}A> Q`J)EU[kOY:m endstream endobj startxref 335109 %%EOF RProtoBuf/inst/doc/RProtoBuf-unitTests.Rnw0000644000176200001440000000420413005133352020223 0ustar liggesusers\documentclass[10pt]{article} %\VignetteIndexEntry{RProtoBuf-unitTests} %\VignetteKeywords{RProtoBuf, Protocol Buffers, package} %\VignetteDepends{RProtoBuf} \usepackage{vmargin} \setmargrb{0.75in}{0.75in}{0.75in}{0.75in} <>= require(RProtoBuf) prettyVersion <- packageDescription("RProtoBuf")$Version prettyDate <- format(Sys.Date(), "%B %e, %Y") library(RUnit) @ \usepackage{microtype} %% cf http://www.khirevich.com/latex/microtype/ \usepackage[T1]{fontenc} %% cf http://www.khirevich.com/latex/font/ \usepackage[bitstream-charter]{mathdesign} %% cf http://www.khirevich.com/latex/font/ \usepackage[colorlinks]{hyperref} \author{Romain Fran\c{c}ois \and Dirk Eddelbuettel \and Murray Stokely} \title{RProtoBuf : Unit testing results} \date{RProtoBuf version \Sexpr{prettyVersion} as of \Sexpr{prettyDate}} \begin{document} \maketitle \section*{Test Execution} <>= pkg <- "RProtoBuf" if (file.exists("unitTests-results")) unlink("unitTests-results", recursive = TRUE) dir.create("unitTests-results") pathRcppTests <<- system.file("unitTests", package = pkg) path <- system.file("unitTests", package=pkg) testSuite <- defineTestSuite(name=paste(pkg, "unit testing"), dirs=path) tests <- runTestSuite(testSuite) err <- getErrors(tests) if (err$nFail > 0) cat(sprintf("unit test problems: %d failures", err$nFail)) if (err$nErr > 0) cat(sprintf("unit test problems: %d errors", err$nErr)) printHTMLProtocol(tests, fileName=sprintf("unitTests-results/%s-unitTests.html", pkg)) printTextProtocol(tests, fileName=sprintf("unitTests-results/%s-unitTests.txt" , pkg)) #if (file.exists("/tmp")) { # invisible(sapply(c("txt", "html"), function(ext) { # fname <- sprintf("unitTests-results/%s-unitTests.%s", pkg, ext) # file.copy(fname, "/tmp", overwrite=TRUE) # })) #} @ \section*{Test Results} \begin{verbatim} <>= results <- sprintf("unitTests-results/%s-unitTests.txt", pkg) if (file.exists(results)) { writeLines(readLines(results)) } else{ writeLines("Unit test results not available") } @ \end{verbatim} \end{document} RProtoBuf/inst/doc/RProtoBuf-unitTests.R0000644000176200001440000000332113164671424017672 0ustar liggesusers### R code from vignette source 'RProtoBuf-unitTests.Rnw' ################################################### ### code chunk number 1: RProtoBuf-unitTests.Rnw:9-13 ################################################### require(RProtoBuf) prettyVersion <- packageDescription("RProtoBuf")$Version prettyDate <- format(Sys.Date(), "%B %e, %Y") library(RUnit) ################################################### ### code chunk number 2: unitTesting ################################################### pkg <- "RProtoBuf" if (file.exists("unitTests-results")) unlink("unitTests-results", recursive = TRUE) dir.create("unitTests-results") pathRcppTests <<- system.file("unitTests", package = pkg) path <- system.file("unitTests", package=pkg) testSuite <- defineTestSuite(name=paste(pkg, "unit testing"), dirs=path) tests <- runTestSuite(testSuite) err <- getErrors(tests) if (err$nFail > 0) cat(sprintf("unit test problems: %d failures", err$nFail)) if (err$nErr > 0) cat(sprintf("unit test problems: %d errors", err$nErr)) printHTMLProtocol(tests, fileName=sprintf("unitTests-results/%s-unitTests.html", pkg)) printTextProtocol(tests, fileName=sprintf("unitTests-results/%s-unitTests.txt" , pkg)) #if (file.exists("/tmp")) { # invisible(sapply(c("txt", "html"), function(ext) { # fname <- sprintf("unitTests-results/%s-unitTests.%s", pkg, ext) # file.copy(fname, "/tmp", overwrite=TRUE) # })) #} ################################################### ### code chunk number 3: importResults ################################################### results <- sprintf("unitTests-results/%s-unitTests.txt", pkg) if (file.exists(results)) { writeLines(readLines(results)) } else{ writeLines("Unit test results not available") } RProtoBuf/inst/doc/RProtoBuf-quickref.Rmd0000644000176200001440000000773113164233540020024 0ustar liggesusers--- title: \pkg{RProtoBuf} Quick Reference Guide # Use letters for affiliations author: - name: Dirk Eddelbuettel affiliation: a - name: Romain François affiliation: b - name: Murray Stokely affiliation: c address: - code: a address: \url{http://dirk.eddelbuettel.com} - code: b address: \url{https://romain.rbind.io/} - code: c address: \url{https://stokely.org} # For footer text lead_author_surname: Eddelbuettel, François and Stokely # Place DOI URL or CRAN Package URL here doi: "https://cran.r-project.org/package=RProtoBuf" # Customize footer, eg by referencing the vignette footer_contents: "RProtoBuf Vignette" # Produce a pinp document output: pinp::pinp header-includes: > \newcommand{\proglang}[1]{\textsf{#1}} \newcommand{\pkg}[1]{\textbf{#1}} \newcommand{\faq}[1]{FAQ~\ref{#1}} \newcommand{\rdoc}[2]{\href{http://www.rdocumentation.org/packages/#1/functions/#2}{\code{#2}}} \newcommand{\sugar}{\textsl{Rcpp sugar}~} vignette: > %\VignetteIndexEntry{RProtoBuf-quickref} %\VignetteKeywords{RProtoBuf, Protocol Buffers, package} %\VignetteDepends{RProtoBuf} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r init, echo=FALSE} library("RProtoBuf") options("width"=48) ``` ## Example proto file ```{r readab, echo=FALSE, comment=""} ab.proto <- system.file("proto", "addressbook.proto", package = "RProtoBuf") writeLines(readLines(ab.proto)) ``` ## Read proto description files ```{r readproto, eval=FALSE} readProtoFiles("somefile.proto") readProtoFiles(dir = somedir) readProtoFiles(package = AnRPackage) ``` ## Create a message ```{r createmsg} message <- new(tutorial.Person, id = 0, name = "Romain Francois", email = "francoisromain@free.fr") ``` ## Serialize a message to a file or binary connection ```{r serialize} # to a file tf1 <- tempfile() message$serialize(tf1) # to a binary connection tf2 <- tempfile() con <- file(tf2, open = "wb") message$serialize(con) close(con) # retrieve the payload message$serialize(NULL) ``` ## Read a message from a file or binary connection} ```{r readbin, eval=FALSE} # from a file tutorial.Person$read(tf1) # from a connection con <- file(tf2, open = "rb") tutorial.Person$read(con) close(con) ``` ## Get/Set fields ```{r getset} email <- message$email message$id <- 2 message[["name"]] <- "Romain" id <- message[[2]] # tag number for 'id' ``` ## Message methods \begin{center} \begin{small} \begin{tabular}{cp{2.2in}} \hline \texttt{has} & Indicates if a message has a given field. \\ \texttt{clone} & Creates a clone of the message \\ \texttt{isInitialized} & Indicates if a message has all its required fields set\\ \texttt{serialize} & serialize a message to a file or a binary connection or retrieve the message payload as a raw vector\\ \texttt{clear} & Clear one or several fields of a message, or the entire message\\ \texttt{size} & The number of elements in a message field\\ \texttt{bytesize} & The number of bytes the message would take once serialized\\ \hline \texttt{swap} & swap elements of a repeated field of a message\\ \texttt{set} & set elements of a repeated field\\ \texttt{fetch} & fetch elements of a repeated field\\ \texttt{add} & add elements to a repeated field \\ \hline \texttt{str} & the R structure of the message\\ \texttt{as.character} & character representation of a message\\ \texttt{toString} & character representation of a message (same as \texttt{as.character}) \\ \texttt{update} & updates several fields of a message at once\\ \texttt{descriptor} & get the descriptor of the message type of this message\\ \hline \end{tabular} \end{small} \end{center} ## More info \begin{center} \begin{small} \begin{tabular}{cp{2.2in}} Full Vignette & \verb|vignette("RProtoBuf-intro")| \\ JSS Paper & \verb|vignette("RProtoBuf-paper")| \\ Protocol Buffers & \url{https://developers.google.com/protocol-buffers/} \\ RProtoBuf & \url{https://github.com/eddelbuettel/rprotobuf}\\ \end{tabular} \end{small} \end{center} RProtoBuf/inst/doc/RProtoBuf-paper.pdf0000644000176200001440000144436513164765764017404 0ustar liggesusers%PDF-1.5 % 1 0 obj << /Type /ObjStm /Length 4692 /Filter /FlateDecode /N 92 /First 745 >> stream x\Ys6~ocWl TXyI$ƭfd{ɯ@&ْߪ* ,8`i 1x1ŤL343YgxqsGƸ8^W2.AD[b9q'i-AI~ %dBӃ3aЏrN,C=`qzͤwä-ڡ>lNqtb*SLqzLIzL)G2<Lq4'b9ӒIi0sdT)fE;M @3ʠed43$AVb0f Ye@T2sPZ$Cڰ#LpaIV'KXyp9va5}c\XѤ~3P;f wfU'PI P<f 8J C' 1JBd@wC*%9He61\"$Ҕb DE=ކm3D>E۾ ٨l"Bv+D4UCx;Ij:L@#-qv_a.dv{ECTJ-vT36m,"8G0R^B7~ՋhulD΍=o4z'vjTwA{DCHplwGt^n=c%r(Z)qk+rf0&(l ңΠr A(zP$ʪmP͚Ogۈ'I2#'L}I*xs,5T"3ojgV.G'MumV̐.ahJh`;]Fh;z-IHfgr&Jh=9 ` m}z3k+v<,3mG{Ǐ) zlHIX؟\L*أE.v݀"X%$Ǻj@ 44Ѫ&FxHsh<LVX= 7ass4 P6m2<hI#na5˻"[ $#m"d$Jr`68O XB ;X(ۦ="i3ٕb#|D&S D.n|l;:`dϬX1U_]EG;l(tؗ527:˒ԣ㒠-6UȈ NE-Jw6@E*2P Td"@E**PQ TOeDsc՟S9Y6!oE-p/{oy+~};*[{aw޽yy7}}'Nuly6P\@85z ɪ|06c6cn$㮔Yu>oʄoゑdt (9ri1-#W䣣l>lVPup9}:FT;%`4'XPdF wwb{Xt\t^;Gφ>Ȇ{]7{t\L0=bV_ۏ geӦz+v%DѶM:Ħ3*C,HN:t̡-XDӳv!qq9yb}juls)o3љEE=夬Q%~E$6YАL/(j}y;Izv g=Gҁa/:N jwE^3bebV]\ e;#£}k#z=w>zྙ7kL~uj7O|j2641XҾ=9 '|CgC뻲=enfl"aӀxFk߂d(r\,/ !!S-\ w " 5{FCқ4J)an'i`>Huycc_x 0_{n,wm"}I  -J+8禩K q Bc}^ > tB{S "{bѺFKK"Ģ6K+Z Qzuۖo$y$hNHԸL8*vG{46-ݝViS ;=[b-fB)%uOT{2x GfG|Zq&ZJ"1{/k$*H=s\oy0~C F柱ENpHĬ02Jt mr@q[}j_Bzg c- 5VyyS h,Z{CP#q=ZĝQ}=/lgk &n3pB(N?O0l%0]5 ߼*Վ&]bCkxLYBW{ 0-ƈUԥעb&mѵt߁hh^ӧe*=JOitYzVϛ<<(iNt,m6mOii-Ӡeg7=4=~rp5[t{%nLEqYj3=Gcw/Iw픾\C NB8 1w3kWY8]7`O.ONh~Iߤo_wrV6m16Nb&YחF3*dRzROS:f,`HlʶjaQPZNE{̋ Rn2ݲ὏7%TS9KGK質#N|%toPM?mX )˴XH?韥(wQY?2wјuY=ɕڋ䷲]o+?>:XUqX Z5|L?9p!]ڡ~qA{E$shCMmp02Α5u~soWY7F,hٶBŕܐ-~[n6+ٞ]k7 ] b\ ,._kN S_Ѓs"SaJ=#_VsK ",]mYTW$Nl̡k8_7MrYrvTU]5iQ!R"!KijzQ#hEU\bD ;?|VY|:F4 .W'R"jÙ5S린v_o%{=&h'_uciz~u T`{qW4}v8^MN.J֔f6]4 u"<`_ҥZquVR\UT #ŋwlL5x\{v[[uׯ?:w.kqQÝ#DjidcB ^ir0/-χ)r:xW{̭>fɼUۯx\NNe|4gv'r^֗-&^SkJtX,dfaeI} V6Myfpf?? {;fثx+dX ~FMݶg;K |29-N.l||/-v"1y[{!3]q2PiULsE[C$`6 IH{(Ts HWF9=a1=XeYjʎ?Y9(&"''endstream endobj 94 0 obj << /Filter /FlateDecode /Length 3268 >> stream xڕrίSAn,YqYcEbfDyk1)\0ݯ_}`w7<_i$Ed, Ab(K$QV*%9WxgݽQZ:<ͯq/wp9l-5!#SG, 7HTsxVI7}hٝ%bī-~ gAM"˥"K'j >z3.HGU\%t_ 才2@rK$bGY.))O<3kC J&+cc"L6( 449iyrg\<'()eUIyfJBv"~=0Y5?_{]Z-m"l BnbUyswMVIyT6Xn>+XđA">pol#˲$ oUUEigL7 YpD$I)PtHfڂ "W5:;vbYy5x,GpS6*#@N~GZ%D|?"p!D#T-`N@iTi2PFJݲ8e:ޣv"cl^7  [%Čeם, ?L!ćNwÔg"l4!G=sFA| J?uDk@_wQ/$Cˎ=xǃJ/F4\z=)$lLB!gXFݑl :2'RUd%^2 kt1%\_xۆwVK ẁhj#PSH%9#CŢn@y3F:sCbnPs۠MeB mB :^dab+eCCbp qgo! xj{T)b`۷Hck,Ȓ($f`| 8}BW`fܢw$e# VBP(|$ش5Cr84V`>% bG+胊9@jnp@*#!.IIL'~U4 !y[(Nt PdbɜJ0 ݁QCPNG5LR b  gTIKxY݊tA5e'u{Nc:,=EB5<-esB-SGhtq!aƽ䵖QNGG)7+IVY^]Uu Nk)ڑjn͖W)/Qp;/yIhn;;hA#5䄐+U XT0 ki3k28,h7&ܸov<\RP%^I'zĭ*J'Asj2BeRQI7 YaZ#81tch&j =ߌg=- ֵACGm=WDz(OE0GY.ךzhN'3/ JJT#2nU< < 1yPaM"CJ.t<d:˓qc\֟4B膥")RpUj*)=]< 2T\bd{+r3pQ zDܑoF{ֳz^<]/_znGwvo0WɹgWnw甇_ 4Yv{5Ӯ|dbJ/!BO v2'$5Xԁ%,Ӯ F9gv<@"4g'\g025ԯ>iix֚IIZu^y"RՌ-'G#u^#gׄRBqE6/bT,FYe'<1pV* N}J] ":ĕ W(KÑ_Aw[4 _+^7&_&\ŔZ9-7-VCvd̻}$q`k!ze *txaMٜ4cu3QP?pRߓS9 y\n yFuhB*ziɓPJ`9.[.?#Q-9&ǎ* A2?RG%kMw,Swx={@]{wGKU*\QKjmT[ 4/Ek5v~(;䊇 ~$/ kmɩp9 UC!Q9Y}⃺Ӛ mHTNEo>O&a^MbͣprG[OҸlUMaAy9a |} AI&ݘWlԹkU\;r~?xH}:g?!DYЈ^ikendstream endobj 95 0 obj << /Type /ObjStm /Length 3719 /Filter /FlateDecode /N 92 /First 835 >> stream x[[s~x2 4ˊcgD#)mL "a ݇~gDlrшXgwϞ9(<LE\"39+MW IW͊RjÿO?L)_FA{4E -fCW4,FN0'`i LO#Gff^i^;%=*p`:#ӎfӁt1 C͌uaIRwcA@ L3b;` f\@*$&TV3 <̹s!\I`^HDbJAth@烡b J8BLe'x"RȢ!4 !"GOg1"?$CXvXda j8V!5JZ1+D= ǀ*D,hbq (4A-G2Hԃ$%3NKBZ#!II_$ [$GKψSLSq$ônS*1/|awU/EYdi3ke98.Qu!5G͸:.yg׎Zzq[Qߴ [&ճjq}5LeS/[ ٘ Ʉ}a83Hvo',dٌq&n@&K˻!ayl<6ȸ"i[g ɭ+9x[t|7ՠ:;\M` zoA>Iܘ*m-<H8 ۶"-[PiߝwwptCK܀$*x>ksnݦ(o bQ\mrM{6ӪJg:WfvC{ ݥ'kh8.]YC˂ONn {dbxմm}qZ񦝈G(M;A_s&0I5"`@uSm1vPK?] >E*e]!'W%Gf[>nꄩN &OG\Ggpy8%sLh着C 1 h W򻈵N>y fKF|3,۲:}EYW;HFs 0)aH}<,O,.'_W]t-i)*<0*NkH !)7F4OB <@AG-lQAт-]A_J+y-)p&/g )!66٧ECxNFďyC[p);@kGbœv4/+Q/zowPB"l6Qp%w:b-``=\,2 4Jh8%[|4Y g;~ͨ..fԉj/ nbZ4L4!t}*^W?d5-E;h0/v# T*Rٴ2!@_8nIxJ(# ]D; \ma"omVBRB#6)*Pא1_8=\􊪣ýWyNN=\&oy{@j\?U;_`\N[ p׹d,>_J+pUf  z"֨㫺yS l'ں[|zh##uV 3۫W 遖ҤB8t;x 2YISzE{b6g.t$k[~+3X^;GE5p4F#Р}T}OaUR]%aJ RkR$ZW\ ~ g?)އa;DtT"FĨ?*uonsnsvN*O>Sѡ_N]iWq虞WP>۠SJ-KAt^P.m cx!~?_1Sq&Jq.F`+1sXVtߊ^\>$ilVN:f8$@w8$+eY= k}ye'Eld1]qWnpZ{z^'MJKbѷx5ܪGׯ\Vm ȍ˾d]rBE߰X+51 }dGkQ|`tNzLòGlA+c6Z}k6났b?شiƏ٩e]W^ƹly"&̮$S9 Ìr (1;;:70 F |\j α{Gwn&F5@i٬1Ju(ɭai1}7]zellg`7.fx:5.j*G3CY oy*}æU".R("6ɔ=?;;>MOuo/a1.z3<=m#u TYV󧹼tSA>w7uu| dhZ/*V- Tv`` [W^> stream x[[s8~_Mjq*ljg$9ZmȒF25@J,Ų圳* lF7 XDU0e*tUIjr&2!cKDŽM=6 L8혌IAE.PL* à:G(rL)M`JCLzK!b*:)4ӂP`PLk8M 3 L ɩ@*3&ga&jl==rJ]zf5h20kʙuDz``N(e4sl+tIgeq7UHK\\"^p B>]^1"$e-WG?p;qf[v=7oO_pj[%DnTkRu5,س ]9Byr<?;/?ͨW?dGKy]M~%;{WNTѠ3L_{]}*) U19m\`&>؟SGb<.E1KO@ۈ<^u՛f/ϗܣWlɽE†q1)/tfٛ;,-Ѝƚad CfcC>|eU{!6G? K]J LJg_uys<EӤ_NsrWմ|a^Gs"e<7yr rEəoY$ryEfGAZ(gTH,;)Ppz^6!DZqc[$rC#PzF 0_Мh*$ 場V]M^{";{0Pƭ7Nhz7O$f\#PJ^}|Š^ JgWHz.B wa/G!Ѡk  / %`^o'$ɦ[XAs:,̒lf'vHBM0%^2ST~HE ۆѻ^Ci:^5>4z{z{KkЇ[-ѫ.Q3;NŠ$M?|9:i"%Fxcͯ*%alKlrXyܜ]'f܋&tR1+ob@<,@C;;TXQ/NnBF{F8\5ScC *ϴy.rp1+tŤ7ਅG̦ŇCc}ԃ֐GP6C7BGBRunO)vΩ .s0*CȬ?hG$<Mv!Ҋ, hXRXh3?J-ʬ`-wz'*';zz3[4Sjhv rHMMN")<={M,9i=bl)Y:)蒩 [N&M%msu7ׄ^*X$y5(Qm%jcP2am?Vșj8R Z4׆3ܛnQKF\.L N 026@Oobb>3eޙ;X5 ZZ,aon?؆TQj]V2;/z}F;;v~#$Ά ݀yDilߝ[+#һK^˒7$b "X 4M A"PrlP:hV)rQ* \%7٨![m>r0`,Z1`jީF1ꪆnuٰS%m̒}w"\v(rp.(RFsZӉ?!DP/%E6fxn罿{]Y&m͊/_zӷ~=`Eԭ,[0KWҮj\bnVg$W#ɧÜAfP$_<(ߙ$6$)Js@ҴTŠ3߅42GI?K:fiR4>ʛ49hIݓf3Mgڔ(n^-<{&oYD꿙s.]Q&#jUƤ0gl易6 L9*Py>q0ԟ  >*3&[Xݓԧy6+dWJ-07+jz,pD9)* :m2=q*1'\FF;v(`Ɖ3)%eܐ K>[MƲFnI^MH8Ruv,}&bolH&i/$kFOb)>frb / 7!:DW@@+n?'k2=9P3U'2qBdb2*w)bc cjWc_ñ$zj|XH*&rY[*Kh:M<Ğ޵ER};6.OS/Zx;-:#̡SMٌء,rЙ-O O?B9):` M;{29LF_;^n#lҦs{H0Γ2zcehe\4#()^aji~vi"ۦ&J7okCthE,I(M cܡEz5PKkO)?g^ `4DysS>/y_KU<>/~Ç|X K>#c>F0 i -g^zRcg_;$iCx9I{VCՠl~r`Sh{rG6 \u ">z;N<("~0zS |zu'J܋ h.w*wK#sG6sky|n#u$е P8(/MEu^ ;[S[`$G_/t$oq~?Fv缇Dizդ7E _Loe%Ifީ? 9gŀ&㚮ruQ41tdfS;}6 yA1^`aL{Ipfrd V+vN\y+өW vN.֜2mjyu5l sf%p\Mo:`K'=}mE&N|˶쮼}yTU/ lXLwe/E_z賮yK!퉍d%fyVendstream endobj 281 0 obj << /Filter /FlateDecode /Length 4439 >> stream xڥ[YF~IX sN⬃$bd(KVfIQ3]ȾzM|w/}d7IUqܭnȊO߾)Q&*ڼ6;x qdDvvw'|M1kZ3{ E?oz, eYf8Jcݲ͋X:6J /YT9Y2;x'?cQokz^;|6+ 7K~)>b#>`~/5wtpG,l"֨ ^f!:T.2@jAfjXokjN qBbK@CF gVcnxNJJ&R$/v^XXֈ(-s 2oJ[t.ǃ,JMP˲@ځz1ZתOLp g؜/T'U|tIQ"~F0$[M$#*3 6, l2؈Yy-J=M}YNX`E^Fv E-12^_'v~XY*[J>aQxx?2zJrV/ʴ.iHY^:t3ҷv}v&١Eb {p+zpAX кv~|w dQB LZVyhsm8lJ${Y'Cpϕi^!,L1+>cDVQ{˒)Ëg/ E^Cv#8=cKZ1(j&ЎȆ7g"K ^|ja4hZƊ-;h+E;;bmqĉO q4šeQV3r<şu/jZۻp+bIg¸ n}3%W%|>Sab⨨\OZ[fv![ 8pHK dp쌺R5@;@FB,!z=#[2$lL$;"RYgwHRPlHFh^~qOb r2]ܱA3㠖_ Ocٝ61T54`-;X/G8ݷN҄XD6˦R倐SIsq&y''aEfIh@|28a( g2^GMb*` X_q |TMU?J!W@ T];zvGe12=wr@ZJ?Km}8IٲK`c,64;|.M;OY8=դ3A!?ZV;92@|zslL(:Ұ^`/82 <$<2& j!@{Doisxl Fq1na6w:ar<C%l$To^J_EMX~LT?k$ vi*thHB-#GL%9(0N+yU׾lagrAQKݦ0O1;:8H%hoAx38šh^9&0nI3 Y ٥ e5Χ` .3#\~hoAɥH\ )xUtry4e*Js( S j%G#mI ڏK/cK][hͻ_c ?OU/SE~Ruɻ=r"/&6ε<%celh8I%q`\sʐ*cIJgwUrV?oɯ[CF[i'[`PN٠ qo2,sz yzug ;N3+;|:fFkl{駯Gx>6AHM@'qgR|c@Kq GC6K<{q϶=`ԛ%8K.!ʊF^%b ~eW+aGqp_Urjtf. |sq>O#r3Ʃce+lxFnIQHl:Ε[rRhU=;qzɫIG$]~l(&yAa2 2\5ha.vzX.g>;D)yC20rkIYO>g(G$ ҃aV]&ZlБ(ɞQRREK`E^3N 6_-^hcо;DMj_u)9vӫwƊm.lF3OL4yOw|Faڭ!XͲݔ^$q8 QY#7B)9 (,u>xqnJ"q)'$IX9 hBw{!p;а"U$:Ч"㰭ir7MBgVӜ.:~NX /eQU=xn0F' oD>NJ/B,qRE<@COu378,#~bwG92ʽ+%{9h80&KԆ[zJBR_ KHV[iiu-49uOo޼LUn3M(r͕?p1V+4g_'Iyyvs~(@!]47Ya%KL.QZO~`Ʋ yBcOZ.eB?rl+zf^YQG vY0Eų3op C;90b5^,endstream endobj 282 0 obj << /BBox [ 0 0 468 119 ] /Filter /FlateDecode /FormType 1 /Group 62 0 R /PTEX.FileName (/tmp/Rbuild5569202a0e92/RProtoBuf/vignettes/figures/protobuf-distributed-system-crop.pdf) /PTEX.InfoDict 203 0 R /PTEX.PageNumber 1 /Resources << /ProcSet [ /PDF ] /XObject << /Im1 598 0 R >> >> /Subtype /Form /Type /XObject /Length 38 >> stream x+2T0BC]s#]3\.}\C|@.f6endstream endobj 283 0 obj << /Filter /FlateDecode /Length 3224 >> stream xڽr_@U0cOE+e-}_uΛ'D{l7|ð˷nBy) #\X~@92xlu/L׶"dHKO&.ܹ/dW rbdSz6ES2oٷGbq}\y O۞0ԭnx?a P` f0̺|C}(=[2Ɩk; V+: orGfZFЎ#H>!%uVcBQ_l=qٶ‡Atڭޣj8}Qpm4Iw?$#ap/ ܎H`)# @ue.qw8"DeZ؂,->ڄp6G7=SfCŽzBbPv[b['Li$=8.@G-3go-G X?:XdiBS.03ٳMt5uUywr~N8t mȸɾ/ @:DP5G y%x;g7XlL'oA !C$p3δ=q& 2&ʘ/=ئus0P=HwO'B_bb?dM~'[2eyvdK8IٞuKe>j*/+-kH'}j4 ҋk wYer iM]g4p۽i7ܬJx0mJƄy)eKX32P{NzM84TSbsXK8fn'F64}Uceo6[<8T[=.sp}}V"ĊD(6M ބ4T[v/"MeES[$BʃYwx%6e&%o8H|QDZ+D Fy҃٣c,>-z^+?sКÔ=9!L??rѧ Ҕ@3U(ę͞x7t;2.+PXvnK?}?JKi3Yendstream endobj 284 0 obj << /Filter /FlateDecode /Length1 1835 /Length2 11378 /Length3 0 /Length 12523 >> stream xڍP@K@%{܃[pdwUT1v@A" bdmr``ad|, `ffcdffEP;X#RV2`2px8}H;ZX,,\VffZ Fόik+="kW;1yPi,<<\D,Av`ು)D@9Wj~S^&&gggFK{Fk;Az39 Xl Sdml` ,@z8@IJ gXOz_0/߁V8֖6V`+1atpqX64~7p2[@BD`Z_6`%2eq+֖ +{@׶2fͭc"mT )L^EL@fff.Nr2jCOwkk O1 psy[߄0 ?_ ?ہ]Z̯`Iu,\12HɪY:QQk;'+z<7ƿ|<fڦdP4%k: ?C |<M(!߄$-,PS ,|~]5UFr0x]+@?gO[/ 3^ hzqؿ*V@k 03pE|}ůpgyD## `bvxu 0C>99LE?`XL!6?`^&nf?EzS8L*k.7z=7ѿi7r&kG_K1_0u1}x=3f/||]Dz]=&k66~+3sUiz%~_0kZN c_? 3@>*JgIm$y{74|WE;ї6ũj5*4=xGL4oli>XS:? nK}&Z6-Dj _7K$ D} f\T15@"м};kDhjX9#|hRW*x~N?9Ǥ\A+i"U*gȚm г\)nvC-Rs0ñ4BB8)ͪZ虹ㆻ$OL]MLr`GAVH;Gs/Dګ޿Nqg<76h UK{j\uXjiY>qav.&&Ɍ JQt~%(ֆ]??Z]jؤ?3P P_̑ۓ>⥞Wi.si6aR3 9<ۏ.W 9waIݜ ŵQi<8 -n'h3> GTy_MOq8r52\ L|M2,&*#v$ *x @kfa{Rq:YÏ!q~dKq(\8*9l'X8IA3^r1Cֆ]u5^V|~KQs-歒oε{G9_:,;k<+bJ˨G\k5@F 6|^X #oٴW0f' ]% d.hoe*g1ϐͲ!5VWA7 $i SCJOIr C kx7nT~GN eIub]1,v6:1_g6ujFHkz~{r}d\#J])HJax:mUH3ET> *\.p)Ews/w;| mC7{ZLdɮIJBg1;嘗qlRux^iWa51R^秼aPו=qGzg s-ܶ ̭2G̫6>S_X. +0 )tD @)ɢk,86;鎿Kt+5V;&~SH9Kd}IǬ,yf=EW?gy ;4AZ~} hɌŻJ<23<.^Vd7*6\[uaŸRLHHv䅥<@]~ .O4fоcGsu(g$طȇR:Ή 1.k\p8Ų,V[Bw͹P?zn6ɒ"Z_x%:^qTIfB.$h|̅ b`hQ*z՝{ y QAPv8$tg87VIJWs=P <##r |s:tJ+}yCQśA֢PĈJMpa\M˳~Z|6s^+Zru3EgOf#,0Lݲe'$?zL,R6"U&d,i_Z>} IZ<"0a%Ox %EF6E8Ļ A^wݷ[=\oå&|?y_ }3Sdƌ@ qy%Kt)h2?&^Fm]rȂRW1t)6ȑ`<%}b@>__^ @;qAZê{mH㢏)!YYL)>c߽X_isJSB W}v ;@e4EuzώUd} )'X%>[J,] q}6#'v!Ot\K\B,=ct'.!"+$ɜ"ɍE _XXl~蹵.^߆ߪm`!GLoL5cH Nc7=}E::*eʳ#a!i&O$1!"ػqL8 a"A՚rehx:vUgax@{7g)>Ż̓(d# ‘ ^mD7ZJץMw24~n"i7׬WWyJ|p -!_X΂vۜx>hmHNʖDs!8$BEɶ 4|_ͷ_ۣ/9;֔C̵}cAM.i;^'rfYbfHs N/kyc7mqE߽ -v[q xj UNrv < 50Rw[PVjvv{g=c^,6І8KRmsDZp1M =-F{͏2d%fucf܏|ٖc[>Yp|q ]T1\]иE@`R+?5%xbh:-AHԀD ifp#~0䄆ؾVƒ]~0)&ywlեNeA2w_"NHKQfIW4?CZ7~xTοD7Oj:sum#@ QB3g<8P4d!ɯ,6Pvj5;Tʢ>ݝ K!ڟ:0,Iro+C=oP r1ol;l.@1?ɍW8#yteaq26bx8EsHWBAP ! *F3> I;ulMl^,J~V6A*T ٵTѣ:E0VU;.W\+.e:֔3ƮA"#V"I~|ysW8ol[}XUBȠBw{Ƃf[Mny;t 4j78Ŋ k Mr49?T=H#(F3yzZ z ے /@gJ^lSar4l*$A8WbS;`=" "]cӵvf~M†@\gl*+"%֔a"\6>Qd.-3{YOSփEa8+MBq;*ZDqO/GP|7AC OVo0NLȜs|{ KzߩͭR4*XQ1Ӝ|mU%`oӞT#d{>3#tV<0鈘C4$+Omh#&t2<,m4q].I#Л ;@mCg<]`08D>KU6tm[@޻Ԣ{uUESOCڅ e;mLZg8&7!_[GqDO:Bz}]AG X[s q70Ύ:,lᨏ4П7ZB $?ReҐ􆛠̊T'D^JoB⣔~8BlU>K8pL8.JF8P^M\^em ]%G}oyΠ8wh*iM|+́FYZv[7,U,k,%?>VXB,CeY˦G|2^N*\EDWUReN !Y*/zgrB]%{(}uHɢ=pk %xv⃧unwTc2 |փaTܛ~KU#=~3xw][P4!>"ܯ)JWWn^85ŎZ5]2(M//p%gb8л韬Bh@hM 1S>&q/3x^ӝ~E5l\p$1-v~%ƄH=^|Bf-J6l" s.U?A|p6)$M{xY^0B`DO`kKfOdiC3j~ۧip[b'ڬy}E2oxneQ!Ek>o.9~,ݑfOBB#ڏAQ=b%)ɇH@`M{&HHXZ/ ℚQ,J,JZ-VʼnQS T?bGo ƚikQT)ytQk%Qj=I篍ˎ^@*az{f֟sn_4tdiVNMաF$u0WFv+Sxҭ 7Flٺ?Yr qv]ٌn&'uJeZ͐{Ac(G?&}ׅY!}wJu2rW ֗)ԇRIf}~ қ 7ÇAтA|}t]Dt#Ii$ // H|}A%=:3=&^ G#Ɖ:Dթ܌LIReښ˺ R/N h]~R}M$^vtsd d'tn_Rh8ٸe)雜L{SXLH nA' jiKB*:d5:\(6*w>oքyn>PcPisjRwT(8mtWƊڟ6H >Qۙh+-)Ȗ6y|+έ kÚf5o`(9DF]D' k\Ͻbx$pTʻ4hvm/o=uĆ|KY[No[[']8|O_sb/I[fDF/\ײ#?v-z|qCqZ.TkF@TzRXg5)1݃'hlJ[t֑ѓzN Df"+6"bO:?.wuxC-Ģ*9$jXāksFVߛQWV[ s |Ken1H7 WF՟]$" іҍ((r,Y!v3/UL G1-/F'&vu~lK/W z~\˘Vxĥ ũG&,V&Tc&RpFi@GBWMI =u͑U LYxn¿::3,bkM"d\b+ukfI61K%kdgO1E!W7T[{Z-7*o?/Ŋ? bwAϔPQbvJ4&٦)5V C7 N; aL5OZ"86l0xGR˽P+m ͷ9oW&tseP Cv{Fض]C~{fB7ӰoMꃀ^OkIkD`;6͕0sn3_;g[Me4%e΢͡ %.85tmW '[Nc>OIl { g+h!][LZLXL'أ#}HKmj6=(v+T}L /\&;ӳghyTSRU8O\V,\vd'ᖔGj'E %zLJ\GMaC#s!l&@IJMV0`kgIe`zgorB;bmxAMNl{10&nvV D~bNyz翔oSNR"fgt2KwbIKЭO$4gln }5(\LS1Db\ȡnh'WJ,.WQtbD(. j#aZHd8hXa@T"ZWPAey7ӳKp<] qݝ\+tOj['NfkѱNy\y0ʙGk TRXDI. >, =|A/)e+3¦ PZ[0+D_7'$9Y0wx6|GM73wif3r(#GCFR J}fPgBH('o%ҩUt4͓f?HJ҄Q`O,c7U@6beoWa\`_~ H &P,RpTk&O@4 S~CO=Z6U8_`Hŗۣ㗿7զTDVG*JYy)g6. hq1(󉣹b4Ĉ1 FVwP?-7QT&AzN]BN)ᭌ ijܝRGxQon]GW܋'8$ydzv8n.ǧ[hܭF4T--Ŝp=B$N>4 ^ƬL2IB=#{7bg~6kOo&/h {h*v\YTmhyϕ[F ^~Mќ&/O_oU &p%iB2Xyy JBoyش=|RoםW wVniT"kx(!$BnY}t >}ưH~;[H-;غ?Bn[`Ek & vjx_G{X9D1 ieݷZxhaX)w{P*Srlmo=sbx[jI%1IK8!+_Y؋#QXoo1JΗ"m`e;xRǦ5t6s|}ruVUq(_;bF~@I.Gn[OJBQ4ώ@ acVkedN?TMt|:-x O׬8,8ߜ ~vfsC\v38јٮ䛜@wmVlZx&_ r11w#s{+_Lx7ɌQ0H<$7l6᛽]%*o7(S\UezQ/v{Z0f(QqF}YϴbPzySk^ 7Rw6gcx7@ #"R@Ǡ(E[l$gW.=f&Q|!o휦Nه  !%wCrHO-}W\L1- e@$9_BGCԆGGyc1؜gąnCM:{@%sd T@/rhMQ`Dl TЗ8-oi-:kewAbaloI. P.ch8Db-SaR0s^&L#41=)?iA L5wO]RL>,ѳ8KpvVVL{QOǎ4wY2a3,*Z\} mbYcNvuaIBH =y Zl%K\ݱw 8O`O4*(CjDZt3诫>en2韕DeO\6N<[b]Z}O8$[Șxy;U=h7S*6Xꄤ{3_G?Hm@іC>T7!+R*+>`44Ր%Cb(X?eV)3H 1TŶd[d}|( 9{^L@yfI:/jD46 "ZIPzh&)*ُYIcHşNIMF/A/86|y4=oc&gG/O8Xe: ºUf {$cA·]\WrPw,;9*͂endstream endobj 285 0 obj << /Filter /FlateDecode /Length1 1492 /Length2 7205 /Length3 0 /Length 8195 >> stream xڍTuX[$PJbfFbZiC@PSRAii9߉?3]QSKaG] *xA \f0{\f=(#B\nm[Pvy`CD E7%@CqeHNY,`aaA)(f .6P-  lb6.."@;7`\lPg( j 6@9n\fS.; aPm+QRh8BU p<W?%C,, n C.(NnwFC 0{-wr:[ a.0_]=h9  wqU, =y_WlGýV0կV,]p+TIO֭ o5A䩇#|ۇ#`u frA.HW?F`0f0Zg5C*@PcЭЯ_+[Y"_4PJJ]VI㯦rKK#P/.A~?.|I*? =vs#n -x?w_Y]3C_ Oέ]]nA q;Cci\ S!U607f< ԄX!?캿j"a/Y>'ηގҿ[ ,DB9;b+7cѶ~ɹ\|M)2vJ~anpK|gmt>x"?sރXߐ`ښ#;dPEYKADbvj _N`WO:_Lݚ7 "~p`~ess.8u'h oT,$gN)n%' Kt4.wk^&6>>u!ua2:uc:NȅĆ7؈3x¹0[#Yq{ ΄xdU]I3}v9SNh[ kҢ47u\I'j#4$Y,lT7+}41N,HNv[ ɖ &vetoS|SB0᧻9!h??'KV1}kMY0iRkc4CG"3ug N>{<Pkty9 W}ȰlEupjlX`LPPRT[|ٳlya4'U#5C}řM.LGQOaC4Zjˏ1Gڎk>Rū9H7ё|}5[ oN9[mHO2֩Ni'W a&[SudV:kI$8rhe$ 9$EQdGtf~ݍbH$U+&CG,CD{ Kj$,+! /`)\4:!aa5>H|k^= ]bo2']rH9?WF!sW%;܇5;:ތlq$uC4GkMA|ɯ^ij}U` {0 Mc$`:ɺ5ހ,LaT6X2&$F0/X&uӪbޫ)3*Q PG `1糹]qH,I ̹a5N^*2`Ѣ*<@Y$]=;G: nNdJBz3jueg~VuVMm;,_Ӿh^tl{:Rw5h'= |8ZD$Ɇ :&&[k|>nP a$7!pzE[ң.t~ϋw-)C 5eϤO8pbB#-ǫ!~KjsMēj.[eg}|}yqOO7JkvWL@a4[NyBݑԱ%粲/R3 B&1+i'vjHRܒ.Q^T@!$9;x=\9> ?12N}.!9bYDhtX&]ώmaDGR_w0u,!Ĩ\ϟ#q&_]m]c&y U `ku~POOʥ7ZcrAR;8:$Obc;of<t-2*˺dlGy5<4[>fZT}{]JfH%qRN׎u9R;auؓ];Ј4KY"Wm whu$K)Z@{ډ6M,TY(Ii% k,J★Cѥf5)Kf1,&_SDF6|nl>˪HNxRZ$5tz<V]G4rÈ*_c_{5u2YzQ1%'>6GX{3cl@:-4+/EX46D{vdP_蕜32.ݛVvڗԤy ~?:QԺؒ;9"qqŤjH'a1{V s=ԇ N1H?0!|B*1.a0x{0+ţHAa{獷 9s饠cCQIC4e咼#Q7<8RۋюQJ< b/v> {+4SXY5{<-xEi^]>낃w >_?Kb/TjQ2m#1uCԝ`n߶?yLk怖1nE1WGP%,)|+U Y^ 28Pi)/jLrYXv`b]4n;w b:>b_^E%T!?ntjN^ivm^FB@xcx[y #PƏ/qCyq,R6/U i祻Ҙo&^reYJA~`MVk3*+_-z^h'V[U=# b]JF.f8~ߧtng"i#DԚduC|zsY7p5U H_CN6^EA޻.]V?qeXyr9o/z'"wEO2+f,ZLkO5e{"R]ZQ={{{Bvyf"!?$JW;T_f#,wb7ո-ϝ1Dz*]oyKخS!yk<8EY1CZWr~CSy"&ء-_t3LcٓOx+x7<Gl6^V\T=ޛy^ൠUh`sE׺lU{i y[{W.oUTX?/ЂX_S4Vxf2gk)y^kH8~'qR(Cè"≈#3LUҭV]t 3u( yjBJ1:1O0ᬋ۱e澇^`Ò*FIG]oFVM_ewmkI4U<ڼL<'õfF&S:үųY:%I'|R-6' r{n\+x[i6N5b 8:%)L=cΪFs&vmjOVv{+ y5 !-Ex*pOU=$K$ݏj X'ODXt#SWB_+gu<֊ㆵzuDsՅ KVM>u ױϡ<_Hb͑u^Rs/f' aR|iO/!.τ޳n.g(wSȶ}iV쑓Fg\Lw45渎H΀"į&9faLBnאY D|wKv/9OC?2=@]/Mm_ݳh-r/V)^ >nj% nmޜ']ut4#X=Nx4I8/tpj/ّQ)Sˋ&v)4!6^pwI c"}Of;"'i ag̅u*vϼ5j(totMi/-wb UDn]r4KLlm`$,&&s2.)tZ9ήdAk,p3Lxe;s} |¬To/ΰ7.b*K-RT[(9;n16甤sE7eqIįovs:  jYb8jhaŝN(Uj֞x(.[?qL;6;O\"2Nhd6XL(k،q .Iq L>!R_.bҧxt ϒ<3ێUa`Z(bO jGVW[lش\paXޔ!LNj-ioHner`B1bAVcavb7yG}SυJxNIOcАz?D(Z]'$i]kcufNX I zq2]zZ9Kᶽt_q pvClJk #Cƾ\N, [a5]59>k6 (_c<|Ē*@3L؋YivbJQp_|*"H{a`*He3|}Hh#]?f2\iʩØCOW~zO!I'/")b do7?ˑR{{op7]5<3@ϏBT}*L/8klO2TQ봧梁դ.o*<Ėf4Ҹ{5Jtg:=V7١jMGO]#KCVNS3\;dt)!fkq3&( BcnbIr僔 IN~^E&: ~Z%Qui}r꽝&E79 m^*97-~]9Ye-&]+ |_ܠ˹W)ؖGÖu]}[ qqS!ܫN)źί5ɝBWuHuv7jH6r[t (CKDiЗ{)*}A}yeDwc풒vk C5h6mM(=D^ٚ,d!~ ӎa=:v*-ɫ73wxfW ʔaS+gSp ǗWJP_*RdbaFrh\br(sݼyio˪dh՘쓌+7V>6O|N^="ĆϺKY?V-\78bd_⡦ ƗwLr!Jq7ą Q|sW;Q -+& ,uُ1c#QfY oLJx&e.0^f7>0ѿ% Z \MΓwyj4CZ JӵoY\>OW``ݶx?-MRn,R-yDN<&Z_P(L1eMہhr 10u h"\rE.0@[EahA1٧Z5U㞃gMgS3n_b&m,nd>mOA[mb]D6]*KySG=*ʽBTq6*Oq5F#p8;/ f֠1ZkYU V$U̟U>i5 XƈǝN'zog+p̲zu"jH3aZP %y[b:3|X&?p:_Y" As"ZF#Qe4"QcbzOp[BVhOn蘾|inQ̫/zB'| _] 40gTH`/.Ul QӢ@IO[ZA0a2ڈmoyy3rr,6roQg.5@6:Ө:FKufi>ynyi8@v/ [ƭfX9m-A`vCm*\a~s6>>\Uwjߩ՘۲Y-q-bR9tHN+cc,>e]x3vlS~6K= \ƹ̱+%aNCZMmܢĤ*+;y?D>`wOl GߝLqYv*]!/~Gұ{ʶ@QQ/Yq&Ԩhw~+}Pzey}hS݅dNendstream endobj 286 0 obj << /Filter /FlateDecode /Length1 2764 /Length2 23964 /Length3 0 /Length 25505 >> stream xڌP\ -; NCpwXpw w 33wWWPk}N( lx"rL&&V&&rrUKgk?bru-"@#gLd'gg v09x9y,LLch5r41lN"vΠ4@eB ` dt419[m@M*v&@gpvadtssc0qbs4秦Y:[N@GW)Wy#ߝ1 T-,ؙ99 bk tTd @ۿe633/g#;{#[K[s5 .L05ehdd7r562U@\H `jL-흝,+ hb"v66@[g'_Z:M@c`{llff0ugTtpJc!LLLܬnb+=/%/1/{;{ pvtx/B`fZ8斶@1h&L~o(%(/*Gwꄅ^lLzv&/q>7?e+ekfZИb@qPKZ 7uؙL@E$bm/Gmdci.Π6}r@SKr6ctt*Z:X͖jhd@epQ/t9M)fkbgX9FF%;t@H `ds@~m(K70 FF߈ (qELF߈(%#VO#6oE7"j@FZE\Z#Pv]7eW@~#Pv]7e@ٵEܠڿ_ 3ϯ6 o md[WJo/bd&v *t= ?0Q7Q~8wN~C#&쬿* ~genG6wul[x[mj̇? hچ;2;tA.l5jP0{?`cG_Zrz)aEeB.@G2hjlԬlhk̿V˜AM:v fetcm NW͂d'AUN z1:[8 4hnv8bAv*s o? (4DŁ"yN繉#hqA?O@;aa΄7Ȫ*im/^ .o`+>9% v.oQ] .?{66%(5?z?)On7#O` UЫ x?;x|lo&tpzq#^[42S!TC LOG~2s}3mX:(5K{%~sTũ W}dKx/Y¼yF ?1o21isAwgzG՞ɷϠvC | 5n|vk*fB*)k5R X;Xx^ ZA,>O&%ѽ|0\=wÉzZs,{Q^mp`pMI>־Y[`OUΠOm:R$" o7g Ǡhr+%[ ^Л/ޟU ) u%V&Г#mB3<~Ss@fxգ-[kN YHCjآܸ`;T&ݡ:c{ʫcN,;{~A,?Y슻R(.{Y6'0oyj' xp~X\#ڲ\QNȐ+>y?@E5"d!P3絥xRd ڲ6bTG^c6 'f٘i 4̓C؞FtVrE1,"u!jaYbvb tkrDwMж0p`_:{TRmhA x!`M@[{!kEؒ{/ɬo5r T`>bL?'Nc zi"'cBWyEҦsC\h!!!א)l;5 c`ہL2\ S.x]"\=ByX<.t27V\ʊӑtrTYiME'@< ё^"߭^ZN{\7w\t v,toˍ?1&O \.]hO6H.y<k&+2!8}DE`w?0uW]DL'{90$.fQmHCsB.323ys:f`#/y晾v=Ǘ>Ѵg%mbaC:usJ g[c)%)lLǶN*r>Ҏr4,#B>r\ԸO;pO'1 DJ'X `asC/D!a8Ũr[ ;R6~&U14M#˜oQT 6ԅ/NSl}/15ȑ3 Q!WoጩUN;qK}к8rT Ek*>\!e]DMv̢HFRVk+ H-;l&uRsP=eZ٦#UkQ,uթvSj:ͬ0&AJfa#Q% "TfO|E('][:je{}l([dq*ܴ͖pF) V{ &}]*W"q[8 ?SN_L'uo*fR)dۡP1}Sk{h== ]T {~ bpi8lڭ nC…;kc@wǹ-%衢{ "Nxn489ݕ~>\<#IؚNG;Ew6L,X% 9LT- RV+˧%:0wc)&w,ϗN'uTWEXJtou7F$zxɸ80)l<ʩ-kq]n4 #d{ ݫ 2hTT@,abD7>2Z.d&Rho)i6H좌8K喵 2,h b8&\.t!)q\(#z\&k@OܳnW +Kͻ`UDor]KGTfgx{Sw/ͯK&k7NWDv_`&IIff ʐU4=^WanBx3"kQEWÈ %Q4;K EU4V ;"X?~em .-1;~PT*4u r2C\EE=v~RMn{ doJ HR$Bğ@]m0?nW^ xxlObf丟A'4{̇u-9p8T(lLivXSC馶A6Jh?di+h4}]^h؅_܆tk֛wd (K")|A*8τ;pc[iQ]8[21aedm JXnD)e^I]u=5t䕘 #Vў>bšHM2.e2Nj$3nZN_7jtemΙ;<m =KT@}Bq lRz =ں1jǮ`D8Q uq5Zl0Yn -7H .>hPf8L~va@UmYx"LFҺ.ٯկpa7H]`DqfA|Y8CXgT\ff(cCcVlmAFP 'x*wo8?(!s^ %p*Tj&qM ҥԿkeuh ]uP'&jєV9r 䌆tH_KIdT;d1έ3S -֣*SdIf>P%Eb.[P,aRmAA)6֬E\3v3ۛ~Qk7t*="ƚ[۫ڧȁ˜1hht?S1j86" }dDcy!kjcNO;ΩF4lʶmS&[7^o*x4N@<д@ ߼ huŲJ~NqUsAhWE6/>~/2E66LtK4DYi;UYNQ$#-BQA2OnR%7ZDp{ЧVKȄS B{H%;apﯓ島8\TT>[)6Vp+ 6Nyst}'T]Bvv T%w]ȡj"^3HY5۞ܼ 5\KWߟcuQYMM(>"oTp!'*BNLSͬ#~|?Iț} ,2<2]u]C41%O1yt,#PIj@F~ozvm:Y⼨tEẕJR3W<ǂow_aU4;W*J-5`ZE-bU!U'鉂m|ôİ&D*n]37g-Su//Z? cފwFBexGPjI͡rH!.? I:Mwhfع͊y/Uh%cwDڵN&xVpOa 46<z+y*ۊB==o'FNY'$9;Vkmi W: i:9 9RΆO~9L&,,Fռl=}8T.+lc|U(++*>k(p3,$yOH bH=/\p3# mF'NFØ;i&b_{D1b(S-XW[vw"J#[t#o,tE(zY~~y8~zF<'QEFpItsBar$iI b7L2~ꦠUC.R"F;!Pkdj|O0vEP/Wd nhT#ZH_{ d۲ӵgR,{dF!Gn ۟9E6sC:>\eO|5^zp~Tqz41,lE&7ld,K0%n|oJK 21&.OT;GjXƏyܨbUO}Śӂt6t_{}=G]CFR-۞=[ټvs&3o "Z-s8hE_fQ$u)5~lhPVs p.(42na.Nn* ‰-C.Ƴsi͹؆EA1 Db7JȋMdRkXփϷ3 Qfxy?l`cvb8R5cc~;$yA*ׇ8IJ#6^XSѢ7)LXJ jLYj}%Q?N5-~gԑqx>[?s:^$RIkqRy4VH?v#KeTp{i)5zQ.8R׃>iLIBrvLW#`̱_1=KϠ?h 8&d30 GJ 5kr9+KՍd{{wAmH=UmNȎ0V/橲R/CD'*ڣ#{Rd&?ń{ۤ O2ݿ0&`? kH6AFm6: Ȑw$BCM0YTM޾[IU$ޜs۞^V+$DE,KJ1ԁH- KEqLT ½"T Z"cJQȈJ规ũ> :tK9ƐһعICGR~-'W̅6EeUB <ށC1;R\fҡO[%]8c 4=-au/3G  sZ9dUN&wP89i4ޓPvts//'کq+Aoqe)~ś|:58NKo2}1.=vkG_g[;Db^#tŔ٬*vXj+?aDps1p lg+#c6$튷~؂xtV6V2'mVwC= 2C} ;P6e8 E`]qVT=nL zQ}Y,Y}4nw_;Ϟ4PU5AiPԝzM,OOyrшQn.;naŇ:p4ڸ-M4>;S0r{r&E(aۧҮg>oҡ1:mq~NFx?Qʖƍp" /8-}>n+at0πŞ>؊+)_$.m1*;_1|W㷚%؍k:WF#Fǘ C{PͣΏ4I?qɰN>vK1QT=xjaRnI2ћuo˩ wcd2XtlW#oKnlA-EBZkgGY\'GwqӿNMRDhyrT~bSaDGMwFH`@!ӃsG|֐k7pφ`g wD>醒-I\_wot>_\yD0(1]3,Z ' `{R7IPk86e4˵k`BZdQ 8!{ľsJ^vPΡњ=׾/nߗ5Kkls"MEGi?Rʧ1ۜ%4gáDmIeRPhv$+wh4]e|Po;hb>2zߗ E/-iIy~4\ȴI;Eg&ӯhdNg2$JDUB!TxFAs@((\׃Ƨ+i?!L{>"4Jd[:ƠhFb6(hJH743 !Z]Cz3&Νs ;NDJc,ozVtN3 $ &}oz(1?|s76'>>)؉OfH#Q ͅ gI> /8꫑BlhWsXs2T? B̯+; )?ZMV, x崿2jf# Fi˝JQh2T̴ux^;)(~)t2kVo=+m_ֆ 0^ÁpL]T9KDUońXN\K0j*MI !%N T Nr(4X' ye6kɦΙ̷\γȗ.=-^"-[Ho=r1_䐙8aJSGiN:j0(JH$cS%9TGn~1Hr2ox3Ow9Ĕ/į,r,LIy~nA%8"eipVa}Db]*J"o'bߛO"Z}H0ԬCYՙ9 ^DТ4"F8Qcg4dmyCj;}kFJcϹ)Xm :T(7d|? IRsӆ^B^ѐc$rFpR?ck'# dEyϿui U-ild<;U4%i"CB8b~_;,q%U:RlJf3`0 <셬_ze? g .i&#~mTk|}SVuv=inߏA [0b(GٞJJLe@γ:Rd /e1~Bv^HnRBB2cv`WJ7-ZJ~=! da1L;ANs S@ A_w7L.92^^Lk{+@x/ |L$ r PH&$4S4+W?hy9ԗc~:abS`6N9͌T5-PCx~o4>UެP#.Ty@PŨ4k<[ݫD/YQEg0ѳ"OumXh* r>Zs ZO6GA:[T_B8|& 7X=AYm 2dϱߒ2$.ʜ*?C`#/Mzǣ 0;GllA/ixM6=q|{S%Yo"fCEH87|CW6aP̾_km);VtTyB 5,sw<WLe"ih>>WR:.OD+Wگ ,=Ώ޾KU!@[}᫹b8+pnGReѨy#VfX°k0V*u7| st]AIQWˑ<?M‡'Ia Idaʤqrtµ2Ƣ3x׬6YI'o\ r{Dn0lg8S*4|y~NL}쓷@`圀ۊvzAz^Wc$.wBYXA|JY%Bݝ1P12z < A?{DilJHj$ /<m{'0z"ޡПp11G>$^49=8q=\#:}d )zpn䔏(_K/=%޼RO%P5X.. a^GQ9 ۬AZtzވg6<1҄2"aۮ"}՝f~dN"R9dH\ae, \F=⏂ۂ2V\9e{Op[#K#N21ϽDkQK˥zݠh)Q"wB62ptZ#TsM.HǕqh|"3Ux\T&a$2-d|?#.%}d(E.w::H(^ d5>!Z4+);%Rdb;\~ YmߪبJyMaFK :lv~) bZ7;CA~\c}"b׀`(< QB:lN\M\TŠ$OS%'&oDO ~sMN HYBIQ_zbyBaJoQFqa~!;1@^ҥɨg?a*nӖZ)}tYla1U{x^֝$/K*?8SΩZRjE^zESͷ٩yoIj2Qm-"G>QcEHxIg(%QKTbaRQlg-"O|T Muj>2þ-_ P3 B>~NVɈ*bm݀~L# ~0o ؃g.F85/-x(;D3n0VݢB NX%FPosV!pUC3!$sjH'uTWe#NzU xQ>`[[zx {d.Aߧȵ ӽ9X^D]ru1S\`0:~!L6XnVڠqs c01R2ϫQMS-7͢bC y aV( 8\3J4,vUQ7 ,=!3qdVfe\«U򸶤+L[.a)ϯrBIYAys \q Zٌ9GԹ%2ٺNwa>:]Xa)M8̸u7g K(Xd&9'9tg ?CBxhHp0%u:",*"}` 44ȷRTG!62 UϺuֺҩ %p,׃Bd3! 7Vr'cWB_Is]u)D xx1ƔOE$*2/vφ _:x5T0~ݫ T%cyI^rk y=_ؔe=> Al]MJY[,Q5"ǠP7}PSDǘ@ggDT+ߤoXR4$ht$mJȖWa5񌬣MrI#i)o oJi9}Erc˶O RӻTkuIEPz\;=%Es f?ne3 ȸM9aYHyu\_;s:˕#_7eYiXAIlHÔGb0pQdaU L~Y@CŹu!WKA}qz|vZV;%|=@혤 piPERX蝲LT L=޶t<_C3O bNŘ8d~#-D* m3fWdϺq9.`Bj 3+8jCҚR 9sW XRd R#iN` "Ϲga0;S7B>Oo^Z$з (%jPm͜@Fιy~-QV%VhyC"J/.< x&hԝMpJP;Z˦"L4.Ư ;0K<4o҂R86`c*#W%]G/;)*tNXlPRncKov~Ԫ*1/}H Ye*pP=ikLyʀ( Jo`KPioBe@6(:^t9[;Y^ ®i]RA{e/aB ѹ\~xJ\F~A DŽ#r4NOہMW8=,+*^lC eyFȚ+PcĒ+6W44xh)`x^V25>L)ޏ&>]}9w1+қ8Ctr i{[V6D#d:oQ_]f dPE:vNu[6_r=n2îOr8][g%tKn:Lp.Ii eMJ9G;i0.̘/TlgMg \Amx3`\y3m"8vUM>BC;7!j8b:np46_wqT42zM(n#}J3ZjQv@aNE Avg*^{Krc7IwǍBzZ=,̳0Qtm}^ׇ> Öx8EPYRe(,ݭkp%U@PN-\]MCF^If61d_}i*4Op'| ø/*횚Q|& z y3$ f~MFS {j*|W!:qʊ(@\%cTbLt1]= Vv}K8xLpZq=wPw#L<lnق`٣w h# Abg]voֹX,E|7Ҝj(/ ><XE`LR}ϒʲzӊ.CTK 1Y&ɂ~ 3q@vUKJ<qV-#CiF36 ~1n!Y=J`QC>4$ Ћ?C6G /*Չ²Q/8ŢE1I&uᐚىS(VuZzSw719 ãX=3o1ckqJةn#tH WXDK9R”J+*l 8"ٚB(xrQ~3TV7QiX+Nwj /j5YLӞJʂՒl Q&%oknRz 5ܸ_l2ְ`^˷oH;t\v`s v8@iiuaF`?no~L0\(q%!HhtUm=Q~, }y g78@/pxOc S~ͻ ȵ9;FEæ2vnubM @aKz^.rp !r@|Qo橌(ݘ/uWP”(6Ed %](VCWұ̤@HyT,`b!%o/عS4m#xş ltx=Ξ^Cd ke hѭ@7Y H)M?nd40dG9HR\џN9=GW.iO>!x1=^G 6)}c] 瞂lǛ͉,6vةn NZGFȴfՈ2Sk ` 985M܋DEJ*77q"x=eLiY!/#{2GjpJ;W䞦?.#c'orY̭Qr`]kJ:W%h- WK.Bsia1cPO§uցpRnO1;UxȏZV"6>ɊbNiF D<;Ԯ RIU K_Y{K&w7춹cmC_T-if7FO xVCVL@iRqN:-rjƻMSUN}#SeI]TkA Qr,kxgΗkEkz3=a^^&lEa/Vd9aY=2*ˍDBE1 A^ Bc^v"geMqC@0ddU8-pp[W"rCnI:IU#jDb>|ц/gb@O@Q&SS{P\wb\v#vY.V1*:0y6Gc .Te4%Jyp<Ɩ_w;E(sJ7Ūo,,%ɨ5O]q8r;\H/] f?uP!ݻVrX)H$a,ⵡj3f .2JwQXjU~[ן @=P20M'j U3-|&^PÜQY?$Hia);bd D`{ U&NEi | $(JX!@)0P"Q4w}Vm,4mjQ$Qz xVJ W;4 } o1.UTHbyLFwGvYIy&N<5@=RCÿ噍 ڷĴ5SܦyRZYt8R Q=37cg Lj'@sRK[&%\-]@8«o6z 8SC=a 2x2B4)6[yV[aL A95ìw/nY 2d~fJ⧸]z U1f,} *eIeuMz: gAEO)YW כD*#}A"ԥ*|;]~ AOQi&JQedR aO X&mb60PSɰ kJFR"(YwQ# s3/!*QX7$B\Geoń<;xu"Fc(z95ϗb뀃r@걌8Rw6WI,.DXt/'wu:h FG◢pc^r0.zU ] `&aGHlxv?:ףtI6I~6DSœJg,Pcos=7(׀:$TQ?GA_C)qҽE?3u|]8DR_۵Rcd^&cx!+J#xB?=tI?_7Jb._j]ӓN_ICب`"n .EM)uT,~T-{# bW&m㖼lŊmqX{^F/I#׊_Ҕ'3Q( %eTp)od0I[$\@IaJUOͰPE^:d:}Rb툤2p ]a G`OV"F8%uӼ"1޺&C굧s$]V:}=bGw#E*dpt6wZp΀Ă4G^ :_&fAʣ ^9_(fۙ]!3"i,gu_d03S@@Jl3jG ݱ)KR>+矉Y?5%%@Wcrb?#]ʐ6SCԔ"!4ѽ2K?{+NpĄ_:$o,OSj#;w^G c83cd:"Qйֲ2Nc:z@_1תC2'uS">:YRec-CH!8=jB$׻Ln-%f値#xHbe|^@|q.>ʭ+ !ɔ̭ӻe$!|e,ddWQX50":OLz˼2޷Y݂vąTYtkoteLE/Pdw&Ԏ,dS+^>5"z=[!xJo=*AS5"[z^">`,biO-(JH+̻IQ`lڴ7Y5j-L`<.湋~uZeq`)2AΪbLt~"}Kґ 8f0!$cn+ٽaؔrTt|LXZk-u[oSd+2@Zǿ9bZzT~J/*6'9. ^։3K3Pٯ'b3֛Ĕ!n._T1}ZQ{5 \VT]-3ݘ1lX2X$r3el-ѐ@ ƿ- /0,xX(qʀ/P7.~+ (8p:vp'o}x{O5˸ G0!veop\OCc}`jrBZ2&h+y^v15%_cEV9ۤԍ߼' wEDd!Fn@d[% ?I{xhֆ`1~ :4Y I};Ի$' 6n7ká I<^B+y[~ @K^fܐ΍ܕ1}]eviC"x[AD_6"RltYjul.#,3atv:T9jz}.o٥PlRMzz>gAKPhރ/O:4A|F ƍBڿ2%}TwOI&21 5#S؁ѯ%H̕)̵/ۧg\*t|u֙򊍍z>Ш Ta,߱ɼvN TW.gr<`&s\qeuLd{%=heSЫ#k0\Fix),k<^Zrx 9xZ&M[^{ZcL0f遪N@C=z;.5͖KuHalg1&gXy민➽9A NKViP5! gBK;JH{ 6AetĴA݇I~~ #~^Rv5%t|q#U[wSd".6BNvތg ƁDU)޶@[5ܹYC1+t| Kui{.xS{qGmk F~&'3NS[A <8[}ozZ 1ElyD-z4ChpHbRfzÙuQMgY|7|h\kI%ݮ. cFm5}w㺄Ap&NR\Tp88ݎQe@\'o1vp?͕ oLb.'Go8^{'dWXl#_hLoU.iU ߻j-C?*ۨe1nR9,U˺ΚcN}4op w.b7csXD{TV_Gy'MCJ]|>! -%8,nF )?5}i o*]`s\, Av?W+wU0&&.Fk_6E>gr?џTT9!S-"1*^ >YEf6̌/;0T3OPsf!fFW=\$y)@D DiA.cIgK,RIMv~4BMwV0<;7Aa^VdQhA)oyhdix-Շ\$S+}. е@"㏞"#^' ő54,9}SHZL'fr'i"eء!_ d eHͯ!mnJĎĀs\ q.▃t֩o'uW%&}m qf#*:B N*U꒑2d&&$6fL4,,ppQ,N&={"ŧ/D*%~/3Yd?S4`.EVs'fo8b%W.WTV4pc2u/.չx7-Ld?DG|*1Ι)ll" FRޣIsgVe-e@ṕEVe_X'(mad!d K\;?Q( 6.V4_FAQ5-'"'"ϱcr~kг^G/-DS|٣mx4i3DqPxwE;50@sz@ts;Wwِ*͸3'43sm?7Yx].]i玙-y2A# "pf'h0~{ѐm?ڵ|"5jA\ E=Ff~# jv* >:q2bM῵9 ãnzt5`DRoEB [@!,f[:Тr>3y/j4m&_ ) Q?N#e֡V*qh3mFqIT,1+r(bBRl2?[D9KBxH)N:"ԭWڂc i>OQs kENѻr1| 7mm`b\,]סdniT3,f)"mNW $BM3$4$/T7 S;L9QZ>*%M*Q&t7f/ɬ\7c9[dQb3,S,柛_5޽-9t}_ޡ0giA%-u~LoΌ8YЊ% DX0d*A |C26 ;YfPqX9t'ƈ ?4[ԋs-eCU q2EkWrt XU\NonKΘr?z>^(ӯPVk˲5+s$YlQ#T 1n}7DHVRO g ЖÕ,W9\{;y*>t]ʺ0bϬG#CZv{}sl/,!TUWsp۷({)ēV.N`(C0Cm%#3{ɢǞ_<ȓKOƉZb%g2IjU+/JP'h!#Y # X) !~|YI7>-9ٻƩ"|b I|RpӉdz\9cBZhq`ItVӾ4W X; 7&D7Ir]l˫`(R#훱|4ԦWeHI!aTUhѲ7܎'<‚N봇_x) 6:@PGq+w~smRNu)3xT,Eendstream endobj 287 0 obj << /Filter /FlateDecode /Length1 1791 /Length2 11859 /Length3 0 /Length 12984 >> stream xڍP\րXpww 4.Mp%CIprޢY1 LYQ(`fdeb+}de3!QQȑ4. {Y;Mo2 𛡂=@`cca a dP`9]=AV\Ƒ_V L(P_" xxQE3+ĪEgf;d)]E&HRG8K A[Qo3pOfv{$ binۂiL]Ԅ)3ew'e30^bB>2` RϷj+t*)D^hS5AP%g}v6hfFhd h^<1=!P \l?[^MsIbd@m j * AM-VlH Ad4 &uV- z4t0nd[bKZÑb 5N9':82jLZ 6WU_{Џ t\}{~6ZGޟҎhZEs-z2r~v(|HSU&oe?T)3nqDv,4Pwxq %))IKDۂY!kjZcx67AQګ=$?dY]YG9PfJ*?觃&7vVJb^Uя7#,q 4ZrCx[aJANgI9~Q:>(Q҄'FEƞVj A$ nE^}FCRT"IBaugdzJ!.%.﷕E*2n =sxpf) rQ,D rqB*eL8 ĸp <'ib=Ȭ' 3[h_ -nnQ[1 c!QT@3@5p1VNY/<:OuS\4KL_=w\A+RO:X"SlQC) BC~/eؐԛM/!Ud E7@g<~4>|Gu*I&4NO^mI{6 յ[~VP]DBp(1Pz7bfa|;|c.+od_1jvw|p`:E)VIv?(O0.V5,谛eiV l8FY㙟I-NH[gj*hTþ`Wv}_!ݖ4آ-gPV5ÉP>]^ [GӅKޭ6.$J RA:Jԝ޶z|;ԡjyglE>tM4\S;hhc7\x=KF?4;^j:M)C(KV3sT;$Nf*q[,-H$_ֈNmG *iƊnk˺ֵz94Vk3?xF˖+;d*"^ݻ_fnh5ϜGz3+ |gGi]N#fA ūAl;=J߅k>*/|)!,#SDo* ŗG`Ɨ.pp^C5*qzeR,UkZ ܿL:XsEAq ujӁ?\C4K}$t&*qRv%nLtqSE7^wȑ $✒p;`0.gȳ)&osP*,!8c:.N?wH'MK5 ]zrHKi od?gr7ԘXܷq7^6Y[7>uc Ǿd >W#8OCMAsC5碴C O9!O÷5>tǷŞm*!WX"p)ڴ齍R3!96(%>2`4x|_`]瞧xjwwI=ThyPƌGytu;ggGpӷQ_*GjJtE5D|sמ' #_9]pe~dڂP`FIu`Km}^SnSpl݃^+W7=1ݷZj %sM?A6دL2=%3Ɯ"-o-[ͳIqߡ`=ʷPPV52l1IuLHKuңH]_ۦA2J!ձ5uҘj1H̱/k;:~<Gnx} 9KijOzQSs/=@.󆯓@F'$2p^[e0faσ 3>o&" E{S^vw61ߠ>] {Y_H`lN`v#j+.fԄ EO\INϙ#0y{w}vWߪ@͏R{d/&E'X &3N# *wx ~me{jSш&jD!4i /S6 71@#ʥ&ڀWs*f.Ϻ>\N\ dbm ~5œ FșdX>IဆQI{r [hQnj0LeƁ)?SCk0@j vKK(%/m8K?/aQw^q۔wi߂ &e>Z Ve#t!UV똨pYe kuѕ y}jp{ %P2Į"QLsK6sIhLzvlQ>O-nA%i.PQ>|up83' n,,Q,e8e#%grEBBa{ѕfȷ~UDQȮ"@ Z'HNcCmε4Axh@upJ<hW貫uM(>sqgO`pu/glq^p=E up̘4'+pʨn?ֽ_rGn BQ$ ɜAIޞk27<zZ;?\AIPYp{|] +԰oO/*+LP2mJ<ºe)8? M=1\/_& k!|S剟v?n>ۍS9|5h+ٶU%!5C ĠZR2Ǭ/j"j{᛻Nɖ! ! !ǨfA Cl;jܜvF'{2J}+ o֞O#ѸoEd@M><hdAU3uq/nBHqyXP| >~nL,Z@;V7k 8q{4 Y$ګiS۱޻N3Q]UvBйHdry&n+qY 9̋p`q&3?Xn&fɁ,n̑W$ Cyh HkMՑkˬbQ< `)H!%%La׻ WL3h_;_flH 8W􄞉 ^$HCn0rT-lUS?SsȆ̷hTsŷ21$QRg硋@PuљO hWSހ%ZC^ETPh}N4::;5/ֈ~^NUj MCGۢ }"ebȇ8D㢻!zngn#HMVv2Jm3 ܢb)jE24V4|Yb/h(Txx7B"xjjH ]J8~lqAX:em8]u|ᠱuNTLVT&pC 3h>^:{uay† 5&O KNjVRE.BC;G K+(>PZ{7#FGU(AwfG-܈;s8t6:ᢣ\LkaXDƓzG9X_l6@(=2M;ѤcM3p^L[֊i |X` BO]w\k|N4mĈ-xJ; ޽*hR=[RYCy… Kf?2qDNJ6rO.D<V/ kqN-_|e"LxD TW7zv*'Lܝ>+=JEg+׈Qܘ$ Gp!Yy(:ԕAțw=x3PG z= C͌e9~3YkZ.81%i@y=5ҮEK#kܘw'J+ V ^h\}!v@W)!XFXbD#tx&Y33}\rc>8CNүٖdsƽ}5mnjB֢X!xᦽw#d!%b!LCIwwi?r:#$/G כ{WKRTpԳ:yЊGEqhȧWѓܶ.+ln$ F-="Lq;ұh0C$%} fGdOWwḇZ]>EJ&6k Zt?Zrh;γA|ʣU}֬нBGCt ,SIǀ rI4s󌺈~Pٌ8݋-"pߌ.I0Q]0! f.JnQ&86b ֕LwAZ F 5Yy@Ķ$7,e(QJuy6_p*،^ص]x 0^׃M.$oj>: "YB %a|8 "#FMg shʻ=  R9{ bm9V]!jÝM;~ŁphNʧ HpRPCuA~m=P-~uE^ O͍s) DG ّI,r >E!iGcȩv]&5T+^!%o*UE{^x#RRGڄFf6#F fk@ +Cڅ;Zj $g>~3NTC &乐n9<].fj :mƸsVY]J [r.i 0%kYDߡ6_hh'C՟DHWn[S؂ژg@I" 9fΤG'zqXl Kk1D6!'ǫ496B2 3Yѯo)71 &z)uk] H&:AH,c/c ԥ4)/D0¡8bq@3}g]./MH@jj[*iwP ܘM=NH4k›kh͑KkŤ^v?PiI _Rzȕ; \{t`N? S/VD}ԚL2T*͡1\$'?urN\bKBrdX>Vؑ4'S9^i`'e:P(", $ U6W? VƇޒ6Aq>X(z@3MwGߋa~uÝwݮ0E!S:Ԉ!4U+OdW̉?H`>>c|LRqqLBh{4xQ +::2Xm!te6ieT O;X&TmU݋ݖݠhP=it2;Db!R}ɞRȭK-o3ߨ%ܐ[3/Rע]ak,׳nVT҄; Rs9ްNl,,|>܄p殘eb_t ^3G=V&W'1"^>ZTm@{ș9UF85])pjUKƌ_>t4EZ= д,g`wQHǕjl@Ma_nT~n;6$Ps]=e( Țmz #@lXGC78)+b3#G_Kmς4[!pj-*cC ikG#j'[P['dExqZS)R8UFOgI˝K·*OV;U䭒w]$ M ahuL ߺeb|"{tƪĢv~ ՌӬ9ߑ!cKQObD@!'LuQE_ʹS.<,0&>VMГ! OÞOLFJOxq!#e{({ IV=iAVx%|l 2ȓy@1DbӒDdGb՟- 3/\T'_x X(&*i! ϐY0)=;NKjHog`)\7tw-s+O2l{Iu~i0>fq~ECa%t fC0eDJ#N 5EߣT%W*H%!av}}|^}aى b=Q&XTƪ`a)MnCiAhcR~w)pzm/Ǭ!!#$,=|Y}-)P\#Ṷ_% xp/oR9 ,e؛U6cc(2={x5mjBꚼHUj4-_pv|ӛEA 8|?r2}.Õ|>TD^fxs|}Wީ`!CviȌVB.bC+cZ?Y4> stream xڍP6HH#tҍJw ,K,]ҍ H7H( H HwJwI7\Ϲs,= , ٹ8)% . 15!p;_r zm3IJ0(@@_0'a4bPà`g z)O93KHH;@1AJ 5!93 $j ;srq9`NVl7v;-Z(ƁAд8ЀY@N`b:?@-N 9El?;ܟ޿AA0{XBYE; Z29A w 9;A_=r 0f ;cO6矇k AB6,\8G6"dV`8 y`GܚWMo%/C>^0C`% rN.`+0s8 lbA ?`|a0?濏S󥾤K?[[)) sxsع!!!aTA?ڇ1U`s? { . |@gv#(WoE.vvL {ǟu?,akcsA {gY;B7/ȵ~m V9C~-v. tenp8? =M)5YZ3n>~ |7a-i .|0'_g/%x#A S T85FBQ@ !߈ _ p pjp>`/C*A~'_J̮@Tlp^_j`;czf.dS|Y!Aƾ>gVDM}9(ijQJҟ:U22Mβ9n؞* ӽ*yȞ Li#H _}rFkjd3q,l#PpGHlAԣ[3ċw2HvєE\H6GX5I:?ߛӝsY_S:R¸tzgIsx_QFw|:O2\?FdlG.aJ! LP&&fq loB*nJ|2 9Eآ_d{YV1h9#.e k O2n)g!{yKZkhd(RRmytAIge_,u~(1l | lŦ=Q{Y'<Սx/,Q'STzF,lUp8]軟L)70WyݥgYqիQfD};y/LV_${[-L- ذF5Ѥ>/ hX[ۘ*ϗ aMOCgyU>L%#Ԏ2 ѭYmZANoٛl0ry_CqؗH`7ep5۱Ld>H'hB^fnqN:0Rk2}ż1h3IQ!2kfX6X"ÀAug`qoi]=WAĈUvMjn j%5XfZa6E5{X[ j:f]CN]2li Rؤx=?kt͝É4SE$t jl,IgKT{םڧė$+Yv<75.JV+N°'~DCQ=jRO;4/[HG88t2r8}\|ⅷs*C"!ٻsZRL%m#5֡Ԯ({B+epuö%Wv?)O,ovwUf/c|BIkx9 \5nHd0Q#XU+ОLx[4D7D)dxvN 4 oQ /|_/ 8c(}v'{O>Q>֡,\PPEZC0zHN~`ʜUOcM"hE['5"" 6u̖5\/ς>."m \}G44DZ" 1ჭ0 zrF Spch۞m㤍7Ƶ]yLfR[sgq3 Y" ɧBV|ehϻVg)NWܢ|L[&yFnu٧/(m?!EM'TL*>uPa6!q`LQҏ5򶩓lˈ<Kн+˳7C먏T(z4/9iAߏv6&OD?dϪ䉽Bwo VT+8¦i?|(O [;<!zfVw+?=>?5:2xBcGVA]+w`#s㈱|8G-Ɍ/XFsd-a+B޲IQZqGnv\H`Z𳶍~jqU$Rߝ\,d BiK? 3P<".)Z1sF/P;+MJReǼi$:OQ!Ho_^wэ/.]s)bwscI Zx|#:,֙\_Zv͘DV?]w 춅zAK%{Gx/K*62()+><e{vjǕNZ̝Ty!8$sJ0}d^v뎘M)ytd-7ח)n텐up!ضb]1JUǗzW;x[ dG[Y{b0̍m(~< =zr_*pL~}6$xAv #E7I՜d=.4|hɫ.ɪ+MC%z4 dose.I.aZLn R?X^r+EuWcm;fWYrcl9LfČ])5&%?|jEe1rE.fΙ: NSf(i]:nƶU2nm1Jl*<:J>8 ;eޖ͐Liy7l4&Y@+'%ŠRx\[;MK$.Zˀs:xf [Ko?ojrf2LmꈉU=W 4Km^W,Sej&d /j'cEoؖw.׳lu7R܌j#bs/i!4֩ƬʧgX?Ü NIzpjꭥ>?"<ńKgj>65n\Di[GEQO(6eR k E+2 5l^a4#)U D>&`ؤ\?z\}|1ƣveAFa56@aVg9I~hް,+y14Ƕ^ςFGl`.Č1ltB]QrߣF*oݜ/CA"-UiH߉ 5 =e pR);rH+t/[kWdw34 1vY$ReMt?q&.G8W2MibS2-sv'='K%uT #[{~<5-u*j_}>(^7) }&-Ny9-my9~(:л`ChouaF _̒?Tuin:2@3LW4}IوB ц= `RE$Qq"$6 4vqײ!A22P l^G[ۉqf C򂶅rL{9Gi^DMLsPKe($J6 LO8uqE|gorl9hOa~9%$D7-q7d{d*SCKKFf(6B_PRyS 6<2+sV4*YkX=1\j beɄDە_ Ǔ ~K SƝyp]:hTTkHf8lpݍ uzhEsۢ:`Dy:@{ xQsMs[<KL=7&d6±ԁӡhQ֡&b~cS'Y G,8Q2O;/3$XBQհ.Fx=KY|DspeG}]sT[ _"$&p!CÁ2{;54Lp\' I6j([ j9S%QRdhs "Ф5Jon6 TċD(3|ᙾzrE$v!L}{T9nnBv)Ĥ:"RO S:5e&a_γz!|.Jtr1qU~gwi]Yn)XQ 7;DS6{FaŪ'圏Iv6Rzh;ZOGnr5|=dQNjKd Jbj|Th#n?c-iXF _,pt7$[eȱdQ#,Kѻ Oޡ)%&FںmK_t_ZgȻX`u![ە Uv!"ń|Z8r^'l#RX%n&MZQH־ŏgBa hٞH}}T;C``8za.MUT.] fzRRĉկ?j٘160 BJB;>EdYhe=nᐘٟsٖi9$pO""U/f0v Y _i '/&p=W/E_^? rz)tյD2)̽i7rǧ@FYƱP Kj} S3u[jiY -͋kVlK@r*Νhg oaWH[}nFI41FK#Q@D6_U})IB3EM4O7՘ǯg@Eť6ChOQLW#\߈;?QSbTQ#JΠ2^j1\,EaxUV*mUU٥#@+d@* h` ͆(.# .->͐<O .عǯ5^jEHkmFQȣlR +ˑ\r T6Ν}i8o=ug8B3UtY25T }W0cHqP4eEfH "Z"\RTxm@#)i/'zp^s5Xݡ%;uG#ek&ф E\ PDCt0BǤAG5R /Kl>)E. Dv'b_ՖEm贅Mi,+w UZ4a8h81N1ѥtY;^秷UMe+ԦI4My(i^-aԅMhGnKVqYEdTL 2\1d)-(0[|Ip>7m%&v4ڼ2cy9+  m=X3)غHĦ[)( Kv#X ! NeV`a(Fe$iHu_(KS&Mx,as,!V&cE'6Nro5t1}="n@>sA[޼Bm8{ O#)W`+R*]q6.}Z^i.Ф$ ?KUMMI_ۅV˱PTP~$u.%"WߔZ/sw>|۸2++\G>Du={F׮ywk\[qOnA׃  gǓ>Lo[#(@ 7tc9MIh۫ݰk|'[{-˒˗R2&Y7-PC<%VA>وSYTM3^J{ioiIi0J*vB#D,nMZ7.mk-m\InfMGEg佞ri%/ƪOetwEf"8YWQrVA?a|2g}|7r=s5)_ T%jmk܎:m\*tqHց'@611DaY*(1L,QW~a{]G{Sw=i=9lēE_?7sPPǷZSd#3s,CTfO4 hV=Cq[BL S|+t\JKIԗ\<5k񖼞;ZBva"SC$F I]Yn9mќئVѺ(>6?ar4}?R+Aa6e/GT|dz=@_~o΅(Ljp5*[b\E ʟK(;qQ<1QHtʹ`@;eG߻E]Ƀ p)1Q|mo[E:C|yQbL J]KG>Pfe*b[б˱,ĸo#Xni4~b)œyLFJyy MV( C\,qcRS6j!Yw;#Hbh>OtzUun,,,y]hhox&e^Jm (wH;:">8 b>kO\)j6?V<^+γ84W1+e2ruHq"ދ85f1J,hNu?IQ(qk̭t_&uٶQ/*L͑r/ O$?XIOx_endstream endobj 289 0 obj << /Filter /FlateDecode /Length1 1377 /Length2 6103 /Length3 0 /Length 7039 >> stream xڍvTk.t7‹tϐ( "0 00A ! *!) )"")9k֚yzz04V,RMMHZ"7C`p7wjnpS`q8} XN,R 7E@≀- NίqqC88bqmAt@wC@!h@up$`"XRrb]%%$ (w a1 uLp7O8 0`Al&A9"M1X/9(@n9`zb_g%+W!w2 Š\ hG အ+@а_@ˇxBH}@Sk=w.@ZQW)kaj ƺOG:1^h {fk 9Q sscYt$]7QWy3 A -@q?~O8u-r0!X>&: c. Xp_lpaHWR蟍b?q9i@\JARw#1@1Ÿiq="_]c-wA ( M)7"D a #'} Nކ>@wT Ao8:a/!hAuƽ:qh(KbRr Cd% qZ@c^`q#uWI_?4 iWNgi?oQp(Q ZӫJ/~;]QX~z\U`}F"[eLkb4Uş?kss0tߓ/YY ={ .r)g: iy9*9wxfw&лYgz$E$6Ʊ['dNNdʐ}Q!W{'/)9kw<UCTxOzI6(٪jh| 옋5Yy ԙ_Wk͋+""Vol]ҠG(:PvM.l>KwuZmdrx>g{&(b(ץFuJ:LK (5pQ=^pmVCͧMER[UYfuU w! Ybg*Լ]%wE+tŌb9S(:҇XT< l:ss(V bRķe| atC eaR'S.JVMi٪?bDjˆ㟅Qi7_ LJqUKY7Ѭ|,VuBs#qY~g~w7 0y0(L؞..¨># Rd9$Q[YfAL4VQzX6cwiJߦ'م}g؇ܿD`=ճ 6D$Ch v wAG O [:uD`P{~+p׎/>zPw0?$^}}4.!U)ummO}im!=4\m9F6x"ҷB )(`sU$RrN#+fǦ"Dr$!+ktY<#cE$vX17r>lMtdZ>L<2jrާ`lfxf9Eѓ~ qoJTTy5aLS\jQ6ZFՒ3Ӑ7s,laqׅJ׈3&6u\7.n@eBs3V,Gsjm<&[^$_`}ŢŴ ٺ nǽOn个 e_U.jv1NU:i%wͶ:67n߾?zk/ܐRaL\ΐMKŠɋV?ڕzḾfN,7 F$y0=j>%.zASokUڃ\?y<ƙ>? Gn3[5}AOL;{'Gr>b6:o~6BG koxL.}@U߫$Xd;ҔxMǾ?8-5\+1c$\r%cO%2~ %;{K(7(? l >.u\ NE'T=ڋ`pe {MEib:鲋 5Qmz˟kakOs 9,D)WjgfKox.߬5.aۢl [m=>{l6Tl/FIjV˺*^yIB\a0>%0L߹adSm²):}WjQs'tSeWݣ3dPlڴz^9)alCmz‰O4+g==b/MtQ$o<ώ.KR4{DžN#򪥕HQV=JU8  :-]b\_֏Rvسtȸo'x~wle ~@pqs~T ijwl<ѰM*)+m~j:+$[AiWsDŽIÃtU&J]]MHy}b)x䮊cH}IEdvE ~֪zaoMnYWGW7l\e̖o晬{aR8%+ sZ4ry|)Q-ϒk-8W,Uai[j5Z?nr+KlWwW,\uk~ƿ`fV1ɷyWѻfx ]3}b`zYciH]JFDi&}ì#BgňR5- }>-p|3Ui<(]l,k":Ӟ)H{@|)@8NnEv t odƤ7>pV\:*Oz{'JCi3T5Wj[x,PCQm߯fp}8=> 2udv<UWI6D>`pdNokNmW'ȴ4/ZyEbÖU£S='b.AD#=P2jhLǹv$Wl6G/WqAH S_I^8?M;VRF'=ȁR4^0fr0vjM*_m̐:s@󳵞"5Np^#ʓNĸ/tC ᱽrKMU4,;3IhGcY=-O֟"Ovn[>W\  ̉ φN^+㔣Z<8RiMu%G$/À%źϵU2i @>G'[9y !e81,x*9Cp\ƆTPoSWXxfRԭ G )܅y9RkƩ[V [ ^x};9RxkdJҪ73]1s#X7kpe\LQ}jJSPjzݸrW;n9Ú))WdZJ2ܕylvQt*[t PLiۨubyKdz@ 5 uPi7xYN8@#Q!<԰n8ug_Q<-2,^%YkПִ6>49qq,z}jD%5<](&nۣO(QhKkjiPthpr5,J"QlVJ8zl v}^FrTؒy| ~kd3S9c^U.X;ݍ{ӠiB\zpDXN_n{{ݍb' PX;wdaN3[2 ;NA.E^ B ;ޣ#mi(I&5km;^ ٹ+ _@`69'B fn3% ]Ҷl BVYd-̶Φ:vhN$JLYmWqϹe?]|f~K<7)| Z *:'g&ff[mia ݅W1JwV#}*Er5IK0Ɓ'1PL3T`x}$ꕙ|`G̵#TK驄xFcjsdJ9FS/FI1Sk)'$+Be %t,vB2^2ŻK'k}Sk:;cu~ن3rpzIfadk]bb۹ yPoUtfE?qqA*-ɈV|yNJ$񸙘v5Byծ[&x%y߽<~d{\}3V!~SQT)}f^)kX(H:\I`Γ-|)ieIx?RFFNFCa^BK??Ub(ObDɺ 0kY ߅LΒ"%τ)KV>>{$!|PX9("t۩5}xCAE{fn 8Dx*`b_HL09qz{O?*1+m;3_kVɁ?4~8];ō3ٓETv; /=]>g IӁzE}kȬ׋Eu"鹗YujOݽf7+Ǯ`B:kZ}m+aj#Ya֡--<׳4{e~ѥTdZsb٥[&G4"{ԫ0ҕ/R?a5W D~ꗎĺn_T:O ﮌSHG7!d8)D ff\eN 18H|=RN*. Zkׇ(ԫh0 6(=Xk,7Ns-6 ױccƒ؏qT~k wM|f4>3w=bc?r#&_viӵzLGHXZBJΜM~W [RP|sTg|IyQkwJEAu=Ɓ W7^~y9>_cG䃝j3T*b}ӋDEKĊ@66˃Yc- >5ݺ$!Dzv,f(XTGy7H;7vxHdnX|xRPYko0{5簨 v:sz?2*435#ГI2X?,_w{SJڀ}f/_9J0Ȩc*O;X z G9v2v W׿-Kz/σ/K%-z7'ubuELakֺ7;>>TF?kkZʟI6sW:1ɝ,pwc$-rxl(:xI~5!e(pG`Q[1q[ bu|`ZPӱeDFzh!S=ADia#@-!x R=$uUr!=ش୷Hg_ؾ_G~HrL덵X>B$Vkފelbc;Sh b-WpM&Sgh1L2-Oόl>:DFCj5tq>u>ۦW!ӅF”ԥG+h icS.g7kѤegN2dx#_cM羪&@endstream endobj 290 0 obj << /Filter /FlateDecode /Length1 1617 /Length2 7909 /Length3 0 /Length 8959 >> stream xڍT6N HH ,%Hҍtw4 , R҈4]""HHwKt7HI׻=g<3sg2kpJY,0(Ȩ( efօ ;ppW */ l@d-H Pvsx ""Y w5@ ]qe`^pYGHXXw8@ XY@j;#@f#Upprm%p< ;6 w[~5 Pp.3@Gf𰀃H# uEƸAp<@GI AVsw .laesrzA#!ʅDp,ֿ0dIv  Z!W.W&AZ"\qO[!7ދu<CW#nzPXIO҄@!dUB eFv s Bl\oW w0wz_ !V%'; #%x ^? Ef :zC}2RWZ p @_D?X% zךC\0zB%;O鿲KwstM`!X8A @ 9`55J HHAmaC<֚îk!P&AC"qEJ ZE5Aȹ{3 C C}608sD7p+n[ !%mp[@@dRA~7,7_ ": E\G Bn 2o-rÑ7o#/=V30+`r)j΍!1sCΡw8nQxY".}yԱz])'-e)x#(Ҵ"nMH{ֶ:|X*;<?,T~լ^^JHXwU`٧%g)Zt x2ށy.@eh#Y>29;ޖ $Ow^_dl;Эb65x5);D|N^7b6NStxpkv>o8žKbIy| ޭ ET8Od9pHc=i 1Tǐ-,"]CҹZǵc*n KLf)tmsTӪsUIh<FNxi'$EXC\YF>׶R@A7U2ܯIDIP 5Cpw2Bґ0Ge [O]}*jLЉw17pvm`QOQ)w0Hǃfxi[9VU3gĹ'dԚ#w]7T> 170!F?|ѡgK>>g gYq@ 2_c S,3ށv)ڑ4qCQ'?OgEvjs?z3hqoKC6ސg ߝjX=J@EX'E$i}*Cz]+Xغq5+qدH.2ݛ|W}\x" ܤ0LdZ+yMsn]-=&'~Đk]9Y%,TB~IׅUa+pEM!o٬$})! ME($MU(!z,ԾLɮ9kvRq}O4۩/1T݋Rz eIK >V_mS-sqi5Yx8M9CR(Lq2c zӹ,*cܠ/5A=1ˑN#H/jq TJ^0 qA|9;´B2M˞MWk: QV?藱65"okB豹 Xu+c盒w1oПHu fWѝUi33gˉK7UnEu4yc)v黽zJC'/ۜ=P2//( rl{v1.8tL5%wG [[pxxH0eoTҖi'W=Vh]ҫu>2>OOmqCK*EP-;Y5}UA5 ӛ:9w̡V !AaKnЈ'u4ԭyߴ3Sai-W3u ߲lV$`kM =-`pp =Ou@/zTx&h,4we=3\Olb2-hͺLnH+VXa}_!iϩym. C\Qł/z^D{=㕢y>NylKA%NeөZUz}vcKzrE)䪀&+\w[2RSF݂.뜊ݜ6)ߏR슐#8%uŝ_ToHтR :Ӄx֖{QMm%g߈񞉖=Sp]5V`,eRh~j¶:ma{퇨tʲqVS̘e*l( /5W}G69,ox LB&5ܘ{ڵ._RLdF4riLDSB ЭuNNta?7*6ߺ2f԰Vn^T}9乬lX[i*x`/FA]n匐fmPPd3=o^T)vl;)_nѢl= B3nsO3j5wIU1 O'$n i)CK+ aow##4`#7I X}􁇞Ι\L(@|I=~MP7uF]ȓcog{/]}MK:$f_\LCirg3 syamH;pu*(jo)[n@6;w>9]]%(Pa{iD2Y~$aZ{CSvYJL{;(fզbIw=rJ*P;RS5n5R2DXyYv=6H\o jGÀM-*I7n@*;)gɴQ<'MeGk4Krl &5\eQzIqҘf⠫t'}TN7y 95@ p_1{ #\#S|6P xr}ǥ B1QґٛV'5s薉wL&@>ubѩ)|zn v@=?1]Sw\ ҦAoS6AZB'oSeMX PLtWr*S]􋧨)x&j/͸C Y5*f4(4ϣH$%0tqL VBE9-A+ pȽqXi,'Sb39AS]?ք(+DjcV;٥Scq&zd k?ɹ8.u%âmVO.̱t;?d(;w6T)mZAT1[ԵFS.\wnV}ߨ0gNg t3N1X2Wżp|o:L cS8[l)GN%]֔<1VIY!.? Nf%X>dԤ=DBwHAi^%Y&K*5&uөڨ/mYHMzjoƓn}\7m7kɷ;gr2&E.GL]$1|I|[(5"ALWcm:|;C=:uG|]DaP>c-Nͣ{ŋcni*~#'?jHqa?-pQM7T{RbYP'5%|QHh d8& ;i|G6{J 1ev~4ݓ R X a\av|~y*M^tn.˜x΅ﴀ%hk>Ǥ`6H0FsvŒyoH2 kL05GFbQh;o  /8j p"1ĒO!UP#l˭ݾ[KaHeEd N,] R壹mF@do1{=QA_<`" IaKGу iw2 E:~EW;(Vz;¦t޻҂9m[.'3k ,{A"0IiQ?JڡZ qȡ¬\>usu}tU:zuoٲߊ܎(l_) Z\T>YV,eUny7#qBj8tKʯؓuvg"I{,o+ߛy!/,.8mmdao SFol3Zrb xb[rbk>ɗj㩲s {>=BOJyѱ3beT9vcp×|g[K|z&Y?pQP[,c%~o}Io֩__⼧t=ec@g6}c-''t[ba+?n2irQ񐯄a?qY 9N4nJIctp[5&?[?agRw= o\FԹ`rR'*i n4 ꏁiv '>N’̆ ._Nd[e?]}~wEL|.Xo߻߹O~}=EMrYqtD []7ر_o+ߋ#-2 s|e|jZ;ޱO0u9^//¶#:,}Faf-Gp[5yIƮ o9PlbtWAB%fӺdޟv 2dKk4YRS $@1Hk +4MvLU@ ̡Ш d*]@|\[C\٭Wc-y:퍤P-Z\uV^85YQN2#5c|N&ѺyCt4l(5OCStO@oWLjoLVG+A@477V@d痬;ݫ?iBv>_l[^H(%sb˜^;A@j`Kiz3gZЉD,$w,\Ve%;{8vT2ZQXݡGy8Էh=!T1l6)c2tO3 :/I6ȥ?ϥaeҵaLҠ۝3=Rahqs0cfi/T2RO)nk?Y4LFHQ_Xu<ө M3TZue sD,rBgӝY;l>w)Ƙ}]~ FƾA.rd m%6 XEv-ĴPέ-Vhh !ӂ]{c{uQ;"jf>B\].eD]wKzr ؞O|e)\SzCIYnY˹_l@ {?t pE >sʚ6젧c|9r-C.@L2Oc[*T’/^C 6-B;DD+IZxOUv)堞{.ܯ7s?j`h:=+iS Y6{5Heغ+[]'1R~VB(v%iu:\Qh=fü!3BB2JЊ(iSفSi Dژ?/>"6R #NG˱Gu|Yˇ}=ľ~d:[+  kӆ3Ѫ;BDUʏZ9n?M-sB T圦NmZkPX2x Փ2+sZsתcMq4[8"z(Z6_DLqaui%'m8{gZkmI(g`ӴvC|kfQl}>,g?;ORGDM>Ỉ{f)I :|EZO4%õ?c93*d5]OFqPo Ȟ Ql uC GmһgoOU-;Pꜷ> O[p$Tec+M{E=[G 5,~7JWAN`5ȹ]n# bW^TFK]~L2 GjE, ˂G첩*!ef ;s4'_^AnW?5clM*<8>W)s(K՗0e^+amU;V l`ȠHTxc 'xv% />FeMð,Api2tr%VJ@|Lyˆsv< e6q{)) \;%4ƈ$t.Џ'՗][oAU'įKqܩ8Ʒp 7:Da8%[#`̸:.}y=זyxElo>ue;{Ǐ+>GaPZ{d:gۣ4 ɟv`~@|)ul"EP6mWKq-C>&#.K[U ?"7 щ7r TUNG(Ldf@I~Kjp/>F(^$R&h /&Tf4p(oKEȫ_,ڡB/JrGyyȕbtD+Xv Djf%q!͚Uj&e<;i*(Y#p]6: Иp~I=p9ǽ>ch؜/Q3d>Kц4%u727gdG"y5 62ʵPUp$wCh4!Tg`R!7BΠPIvɼ,zb __yM-vCjPLU 1< RM 细T{JD_UصŜ\IVkr è:.]p*جL=VMߴKb;R⤽7(y|7sY0jUnΞU~;Q堕c%kIOy,2+xXø7sliИZI EڮޢxzY`Pp1%5U[#*~7 /A8?xKg8hְHnjt Z:J,%cWӇ?6[ڃ͵ŴF 4)Q]N";j"zMZ؋n( 5ĒKZQs z0a=8"bE0Q%~ppp16w` ]FRY:Y>z)i_'0ݼ~.k1Hvfendstream endobj 291 0 obj << /Filter /FlateDecode /Length1 2305 /Length2 20999 /Length3 0 /Length 22348 >> stream xڌP][ֆ qwwa㰑 <'kp\ޢ 3lc1*TԙA@) ! `e`feeGҰcG:X! 4$Lo  `geO ș afmPdȁ.HT GOgkK+:yКx:[8MV@L 3k J Z,,&. gKa:F5 t: P25f$*ux3Y\R\́΀ eG 096fw_lbfw4qvXXR `0#@;[[T&o?3gkG _=Um%A@ _$fokrwYX;[Ն#+PV1o&?6K  :fV,-/[ގ G[@_k $o7  `nm-T3-l6~lֿ~d6a ;?z,zz T><L\&v.V;'먘X[?re,@${h}@[K 6@Agb5{yo:WݿM<6Sz; 7TU[_,49XM4'3+vk)k5ۮyv\a޲XY퐙پ".o/ ﺒf ;7]T=5f-֣/׋e,EX$E `Cl?`C? `CoZЛ?EiQCoZKoZTЛ?EiQCoZ4Л?EiCoZtK|o>?3Co:K\o>3ۋ/& ֎|sZ9B?W A|? 7?곾m?m'loGZY-[v?u.?6| woNK M gv#U[n7x oX?5?U:{3Wg総.K?/.4C52 i#rgcDBޖ$pU ȏZuu^hjkŏtgKE|G1%iO+i:̝!''Z|.IȦ+ҷ,C$xEGK9?FH%PC΋a!s )b׮L?rzҵͷ$G48CYo`\_ b$;]F1;t#%OA@F5?%H*SO; bNPXots2!~@WYsvkE&gEaNT=1^X1^υa߉ ^h*9+>_CJPmN9KTAeo`7Aqmw\kSUR{vk(Ӌ,X-4Iuz=D}ui1-]I- +$ Tx\0 8$e5g%_E3_丂TJ}Ig9Z> Lk<߸>^dԁ |"39ҡ-T- vMJ?ț) !%)JZ36==sE|ޞ_2UܯX'Y2ΥHˇhQp`o EČa48nr- v%d72tq6kWYfaK.nI[3Pa uRN Dy %8l%A;smN\nQ BCrRǕbʥR0|p' {xww3ONfyߵ 6, ҼIZ-~$y@xkI ^8-fQLy.!PY@h8ͥQ|o-O0 Eq /;|1@.Y?L? R|b2m fWmL"kk6N@z31<%׻}~ +lDg6fO_sY^IWI`+h/r^YnUݹU]/hBnRo1rq*w3 +X+8/B9U]俺]18úAYA)&A'm J\?SúiϧjZ\ル;?r>ԪI' ,fu~4xDY7ߥ>s~8 [jz#Ne~j¦\0bm*S^K!dl)D_aBP#) .*.$"Ed<͕W[Fp5!D9p}w7І1Cb'^w'vǕ>v>q(ŵ,wi4*3wHvO I3h|]960Cw8 4M˱Ly0#lA>ӰB`)ZvI18'rӿu\ՠHs`0 >pBČcdZE_:> 5+; P0oj䥊{G2!P#a.2 Ĕ]j.mqQ㲋 AS*e.M>dZH !~=!3v63t,vO7CA6pktm]׋7%a?k`uzn)5RaY1=* Qٸ3:q~SHh'2-}&e4e(&fiI+ PsL4i#7gC>Oo|{M ; (HL}WDG4,oTldI9 Ua䎮OD+5g-秧*lQOȆW5CoaQ`StkoO%,ׄ|U瑠h;?FIcF%ؖ [b9ïCbd AЕu@qHU<ɇi3zVA͵پ2;4Rq+uJlfĻ ڏ{gH =~wnbV{\|¼btC?QDDRsZfl]LW!x}j~QyM SS{ɸB~jS>gX)z-} PA0ӭ02 %oKeⱶNxN,0[k\Zr%r]`^8#v4X~5Q .i0j "dTxl;~E^786پ15K|@GZǒ%mBF~~zs}Eo 9]G=SHI4&^P=#`fX], dPHtE AiHey`G=@~cCCUx82e`q*W*]D?UUxO\|8.ALϵ=Q5q?savHmTR{s@{$ѕOu݋k5~R&dypb]Nr0یD1%>8=:<~mF]j4?/%\edN_am `Ʌc}BڗËg|1.:MRaU?pn%3"\tny' ˚~O$/IfaY[hB+B/VYUA?/,rM&WҫJ]˰Xga++pBzGܱ ;@uK`0oKUPgfTZIlݲ:N'ӡiDŽ&—XmLQ0e&  I32m F{1fgYI%ore t;U !(uZhI`&2NH_kq>MwN l,~;8"Y}>5i_|yZT$F,^9z,Wtv[pS23-6Kb. _#A.l~H}XvjV=SDܡ*e~?')>wJR~̥+ 'w`FZ͟ը>.AE- N5ӱ`2f,|ΛK̓Ot fVz ֔@ 쳧j TO*P== "+]T. Dnq籰/ņb-X'Fe-\h+5ZrNpڱtA3LZxZHpt`L5 ak0 5HNT780bXJo\'>P%,RY<%NaVRb{yP]} DV6@,Obxsﺯ4\*"VB M02q28i5t8b_6TM}ݧlѫɻ,`f>{wU2:Kj/; DQYQoO9Lץ@L*AC=DKYQ}+8#쌄wb5A $v?0TY5KVHC~M8xwbQ䭴NLV@ +1 ؈B+(%'S8?=Ţĝ@}ȠˮmLDnc,?$̐srf=ʵ#+LMd9N5*Syygj:e0̩g\ :a6.Rق;a#/+vUSkqkmMa o{e#i:Ud%?)6ԯb(kdg2y :>Y+p!+=tJZ''NL,=nvox|6J[ +ZFwr(~=1#muuý"4,cEP@1A?V @x?/"fy:\ rO9aNU|,dѧbB #B4ۖ% }H|lhd"Oivd *O$SsͯM" Wg8cC+D+w$@w.a8!2I:Vw9CUZbg/Sʹ4gE%xQu9k֏'d8XӤRaPUgG⃜ [2@2松nuɌfx+<ӷJ*|SKs= aPݵ Z}¯td9&6˗= -yꆍoqΊ z6& Iт'Y^7HL{S\g7 )m%Aa/<$%y=E9. ,S Er% α`':-,j S6m Wg1M؃?LR])Χ5twZ(ZT%m6=fR*o^hzjZ{ &;/a2oU4Kɲlf9joZQLa/չvuu|}iKj\sN8I*T3rl>f[fP]؁;[Vҽ" x,גHNߑm@tfo[Q4RIIp!P!@2Ԓ[)`J'jZR$@l>0V%(:u|VH : 蓱9Te8HoP9~:( ) q)|A~ԠXN\Ӏew ޻=Oz }|UE{`h}#^YBBʼt2`'49uG$.:-)p@wבTbg|F-kvE/fC?2wtSۋW{`o61h M Qbg\uS6x'PWubW֗fji4Dߢ# i=9Ld'h*'ŲQ9꧿>58 RHJ,d^ڞ'("ܔEIru\ q)y~I?NeHn|? 3 `8tƳ|M:*IoH"ӑ^iy {7I:KrG+U&-3YK:E_Y&*NEnn"eVniEy&(B^ BKHd"bj]̜(;jaüEX~YcME*nv:ӟsRD8gõ҂4=N!ɍW׭^Z[5!#7JQ?0d[t ui)d#G̨b!忯%/ &%5W9@ 6 q~6u[@/1*MWLf(QWDn(mvQ=g+Gzz}6ЬҷTkʏ1wHE/ld`vK]|ə f~&m <^PZ2j`uvY_,2 l[K:^6G'̔iB(e%ͺ!m +D<#.rևX3jj$5ؾf- Q4*yDB_( ́{-$buoTȑ]/&l^;yS`_n7:BN |k@8 ;f z(~&*CCx SWDp+} +H߆jc*̉scH8ԫ Fnnx_Cm'E$h]ycl f=tpzDtg9GsX y-[fIui4B/zVG tb/l!3W*rt>Ӳ:nO԰wF䤰9jcu|j\ 񹺰er}ԷHV ?aދ U?*0 'c"J-(5+ho݆IzF6B͠*] ׅ77q9onsE  g1mz^StXKgNWl( ݧ98~G}2oGBŝ"—j]Yw0gӾrG$<V6>5~nKWO)˒yʟ۹(6o*e%SIV0OÐYsHKhCڣv0cXt%0d @?a׉ }1? `_:+fJYzB-2Zjխ9uSĢS|{܁^ʖըNoUl3D뱡.Qhփyڿ"b7h $>S78X}N]iڠ1c;ƈJEEc5Hwe!ǁ.V {_B}(0C-TLv:5gPbEX\Fqb'9t|Թ^W,w5p֮\H{/S^gQ+&J]k%y1RN0`]oqe*7ʗՁn@6ҿU{A} )#װgܼ5 0?SbfXގY"KslQƿsc{w?wv@y)D e[-S6okČ uɴMD~6rg-llY*/@WGm-ɻl:T218Xb \ub盂kmyJ8i̘1/6AIh(<)$n THSm?սb3sX@FP;Noo<Ǒo +̕a{; sV:gH0}8@ꡗ NZݘ񴗑g"؋V42+0vk/ؕVjfEnip۩4boăf8"!^fzkl'g"o=3ۤ YEWdFkr1|g9)`@&G3 3F tJ?t<'{S+Z#M3Jd*cZn)q;z)VMT:5bsKI(9W2AhaKacΣi#x ضԎW0J -z[n[cw)&p-Wk(]U~Ұֿ~~At h̲l$À&5HѢ8ozZ;'rFGSHBf\bJ磾>QU3큳4S'l~Xi} Oy4*=uG^ \ |zzg[[l6q 4FMT[KhUkcJ6zCVVI+n %}PזQ%Ój11LDuDH܄4j; fGC-qΰ4'9nZdEu=IY902^?|Ǽ ~*R$=NF*3(_n>k..E@gɤS]eAbBM]Z |L"3ǚ[gy.g*Xcf[0^C{^4Fd( UTp'M L~S (4iTF/pP/]XX҂[,]t^^+qImkaZ6y$V|+ڹ*_|K}xe% YXv\IGE-t?@{29~ Z +t_r`Z&3p88Ƞ}jTg ]SY-X}@ 9? doͪ' Na9Fl=_('*y fD^5x ë&|+LMisǃ+B 5ςN&> 3bmW;L\%]f aV嘋vT|!r7_˱ 2>d/B]ub⻼'庄R}^Ud۳#U!Z94oƽI$V]aJ7 "m%6ѯeʅX42(8zR!EW~H'qpHO =u}.<^x#9dWvH܃mYH!x53ߟָzuMب̘dUn1Ƽ !Ho.]eDSDf--6}΁lIͷ9鹼.Y\xeNX,VB q̯N_!-%y+[MfV~4~_$3SM8Nȳ8-Z#q^8vIk֭{ykho v3xVFrENQ•}(oގ+YKbkټ=S^UeYԙ$ZecH`Y>K6n3r⠽_bu#4[ōcmj7+hǚ{befiqs 3_q;G@%d?]zzLKZgdnA0HwcIl9_NV 9OKqLqݶY "NfR*oL#>߸37n!( WvQr X.V_WMxʅ4%2h  }:CN3R#it#Bwu R|2t>jW$8鼯k9pJifb/M5ƞʍЊDv_ޥq~ ΂+Nq,_:[r.'=<-~qEI8(~P%~pس4)! K=~Qw07$HU!M6ѱK[>,T`|PKK$BPwsw  w7裧&ܟ}h$Piqp4 +٢c'Z)^IQyOc(~$pC0Ô8OJ[ϗf6ↈx*8ƃH>0Ib*ҸCOyE{<ӏT jC&"Ց۩T6+ QŪhGİ!yvK`f7tLi|#)@m91hN28[}R.ge'C#)4KʜI[eie!34y`_a%Df]/ΡD'[} {pL6M9ȖQԨHÜ+Zswa)[O?07VƆ9{XL']E7/)x2]9zB*9-2ս&o#Ym*C|cz}oTiH|UL,˝yEp8bOnrcHh[1TxD< _mt4yZ7eL.ިw.A pW 9t:mtuXy\-B{঻6 藨{<[)`CʙYHurhS?kjjDxLQ3^~|;DG^6M[f(|<ɘv)șWĦ(9A?,Izw~CPy6r8Mws ChL/gvL%y,Pn` L[T͎ c)kqmzwIk^{PEE{cLÀ O/}JE5>kzT߿13e<1CUy?ƒp]l"҆/^?zgqP'"D~=nW1) sdyJ:>p$HN&J6fTH{ oe=бq cgҋ~r{<0%s.gs3gzLL%3sI¦95M4F;|/V p"[s1yI,΄Gv*k80\=݊s1yUUl=r5OvĺGTw8ka< >=ؾBC֧VܮNJjwK˥i At޵PU~7;}y "ޔMz$ _fXjAws0LH،Ia3 ~}9{C+ WԺf$x#@}9m8(])#y"ܗkzHoUw`+Dt& }_Qdw2IY\6.X ;EޱA_tmXijReQN?zCe3=E0s#n 'E9v /s?4l&G³S0S@c#qZ oژ|bSE^`9 9nMiY^٫iwKt;Y7CXn kjmRMDf h ]9&@(=5Nkjq 7w=㞠UtSdHp rSϜtX48+? Y/Zښipys~\=MFXojr茍 A],'{{,"sA7SIS:q{tA$8 0PEC:}l7R-D?i}Q}SF(Rˤ .; "겪5nY: x˙5T~ Tp4$clh(dH7 c:;Nl<-1QQskV|ˇ jn'4g8X71يD )LAq['pJ~{]g|u~^j.X"͌}eݙF_x1KchW۶ns.+3k|QYXQ{mk'%~9~dBP֥ Z.&m3㜄g̙PLs&-A=9rGO^&tOxaT nMR| d& O:$)9AyM-LP$ UIcF|7`Z2M(Qwh^ž#,}Ew2TPlsi"<~}s@*3hky±A(1(UB3Qv;ڹkg=6d(?e0*[KUU `UY188 wZ$sB,BTv6u Q?Ţ='B4 ~Ɓƕ7VhKG`t6k,楂I朽u;'}+wEJ?Ɇg}9YҌz0W!XZY/T):FT4CrAIg.2N,Ӆ <˨УR#A=@⢖ ?YߣX=mF:!M?LvٹK8UW)͜oZߥ5) 3 uF$lCɤ//CeSQP4^WZj"]x{D [}HIQ?"l$30 nk‘ř ֕Riji՚=OfiM*ːsvx+\F`'`{C`zU+#vts\CkҖ1kQ~ɦ#ffM;c=WU@s! Ɠ`NТZt$DDI )1ƯJDbcyJ/}:Wi2dsLԪu`&WD3H&ޛ-HIq*}및eRi^gto[Qh{c "vK}T 4/TQhJn'm^܎%: +,!&Z!E #:8{JkY8Z_EO@Ztm2(lRj |yٔ&=vrYO<$翠˳6@>ȟf{D~v'^2Q24"kk7rS/)_.}E) 5O a\( zӇsIŞwƖ|{먍pf@zqWT{6Z + ?eSn=  pNoC35аPG%CA;Y&$:ԟxvtшQENm&V-InXA\|^798ZTw+gn̻ĉ6E ss`?gGcFPMzlRVV} '~5b?#4xN$qLފ2(=rŒ=>NrER7U9~ϕ g|K܎)%O5J(?];vAwMFazTxkG;z wXo%:t ~r ʘvtי`sQ!C&'d Wkg&"S]GO@FN ܇]{zu[١W2k4[<͋dQE@%"g`. ua߉pBK{93[iEhEm?ASjHMB6cr40o;K=VQ dk6{{ K':Ifd0e CNb|ڷڧONN*҉ )p=:WpkKw\Pddݙp P:6*|V)'BzSu?W8"Q.U=ר~o^57ӄ^},C}2B _#{KBtϮmPeTJN*KYg!0Y%S?Ebkf"q(LꝒ)<=!A[>+Dn lsj7otd@Glx^ _=AΉ9!7MRT'ϭ4l5mi ww{8<݅4YEܙQcvOvpU{p-QPZ,nIH˵k]@&f7ΊyVMdِ_V'Q=M>F9s]ז>Sǂ}n1{h`) J5`s>^l*1L-^ ~H`5CFPW֟{` N? 3d4 -3({c__r].2d92W@Y鬃0-W03Ǫh5-3nƶo-(טk֯[<Gr*@ɟp+$쿈?F؏H3G gu~ ) Z1aϖz_PIx~%gA4t t:sPSJs=wF&؊8">O,zjyJ ZkwEAĚ(<#Ƕ64L"?nG;*d5fs5SǶӑB @wS[\ @`w3S:ER;OrK=lZ7-'RJ6үmyN͂HYM`6 Ef1?HrژN7-" Bzpv\{ +һ\;h #Qq ,roNM%#v~Φf[CQ2 jȿGSKr IN}e"-8L pcpnR%:UxSyor Neoh؁~V)5+sn:NxSQoe{TNq Htc7?[AÌ-oX|e[?e:v%,klz6⛧#J-7WwT𓱇͠Λ)8-U˒v%,0iϵK8&'|f; 4]_W.h$Z47KaXSm~z%q"vY+ Z3S8Er W6POvuс^n"0b%0A6X̀yƅ9JZVXp;t  !ma￘ z/Ŧ?;T/f!}C.|°xqÆrZ&Y (FvzP՟z;&a馽UɊaG?tw0H9)ܸqWw]vgG]Ʒ=YzqZMQwdSaGmQ=OSBDDRE_L!Bo EU5"/lI@ + woXD"f2H^u5тEsJ<v8FF%? ;/򻰗G"w҆0ڠ#1Fجԙ 8|.. LukW|T=6|'H]եx>گC߅f^ߴyDeu a~v߭O/V;2NG&f}r[8[}Z J.ro|`Dl>0]JǙѽ`l|,p=QE|*EVxX,B~%zԛ$QHUfǟG^ 5iZ3+1~a_TF5rT:KFvaދDuwkB/ ІpruhLTsh*OȠ *osB+:mɕ;{I_ ? 5cSv>ljH~ku%6^/9$:ݒqTu΃XrLޘ[պE集p?]\@L#(krOdϡ !9)'Y?Jaxߗ;nJ]ݟ(SfzUʉLgU `wZ+H4Zǂ[73Zܯw8N:f1Y".ߚv'֩~=GXVz1 O.:34.^¡hukIC Ej|܎STz.[魦y?ǝRfl}0 cTSteM";1x ZOI\e p EutB4u%6lӐ, &;&,=C_0D~)EZ{4 d]>osh! mEÅĎM<;nWw4|zy8a1g\J24D# ڼSs* l[ke`c'ץ{!抸ȔզQ͵sUPQ5 D9yG2Mqzg˹MF]%pk!Ťu}Ix(.<_,?ZחkF(m٦cD/.bEघMюls/.Sþn^Jqe;̢`򸷀)tٹ|$PJ4ƉT!Tc[nmR,,Γݷ`ȝ!QrwcL1S!pIv-S"î2ǟxgendstream endobj 292 0 obj << /Filter /FlateDecode /Length1 1517 /Length2 7892 /Length3 0 /Length 8904 >> stream xڍT6.)H 1tI J 0 0CwH "RHKt H -{}5k<{?{yaa瑃 8/P4yXX `(Gf<#+K l`O9PT //"UvA5cQ@8{lPwk `E䜠0k0 FAv;0(RK١P||`'$/VCH;0@ 3^< ]aBwG5pC 3Y/7yNwD0`5 m60G(@[YD#qvVw?r]v9H~;e%8DxSB݋ﯛu#<>b 3!)M3f EDPڎwz/g'?g3 zC(W7?@fXAmapd3Cmw iN^??˧W#<><a~($[w02 U{wLo=ΥS- [}RYo"߂?nohPwR &ss_/9흘yBBaHe'CY%솿G o]?@ z7>=g"+ 0x7%x]G? t~ qQx:>?0(se"|w">?]njz7$yw(j73 m>$ DsucD御 uy,=->}D-Pp[`B`-A>Sӌec;Bj&R%o8v9>"Pv^jn}(6> zh\ZK|D+y$;@y/ 3[č[N"tV?Iے~`e+ v+䀾 d:hmHh-! $c;j$Zn ޠُ'm~La\w3OI!4oRAxú)[5l NjO?Ny 6 ]/G( ,41.A[A `JDq_<΂V1t FEDu2B:j?=Z+jIlpy[\BS{1┟hIݱ}*6+0g)cm҂ށn#ix[h|L 5;qN9殞 >K7T#`Y {7:]{KBpn VVm7#p"_f/rUfFƃ=xrN L&[OER>[ŒCi Lp'P'NmơWG6 u8;o?\Q|@vknjEAh=Ϙfvq/ c-"^vl)xٿ~fv`KaTk&P¯/".|kd$t~145s-ग;˟wpj'ٝ?bP<`2ݓ9iXpOaT't; <_}Yfڣk+3['f٭+ٖoO 07(&9 91㏪EJ#&~I!! f?u7WF0f]t>~*IM8,E/"MQ[ᵻcGRy)Z-em;JUYc }F;/Tf=$M@E L˫JV6Ukd$j[E`&ϱz#DӪPRSYqi9\fM⾹hQ4Ocپ\h|ǭMi%O#>/]H5@5aKdn~Լu$'N]L|]QK=jcFZ*ӤFs*B:8̄(iX NK4j|'Ժtfd} !{]'sVã*]iB3@?W3̧%4we;-&멦m`w? EG JJMt:GǙ4|!+ t2{+7~*N+R컲z>kA2~#Ҹ)K5訊wf=scvRcH`Ӿ !wXߪ $\H"nӟ0I1 :2-a h_Y>iG5 XF7xĺ׈%]m.o9ʹ7g-Eq? *.侚[4Jm?'\RاW﵄1p*aA;jٹ/q"4~ ˛oTy٨6=qţ Lj ?%<͝ ŕg;;0φO‡G(?Q͇/{yzQ8)=9ުſ_L3=1KT6!8o[ ?4O=xp; 28dWk5xC x9d%x{EC`&rtLU1=cKU'M,VUH86 }6 WvSҏ, XG{'R ڵ zj$7?B:tۈj~@%n 35P 'yO =bwR(q^]pmfSiNb:S(@\I1 >tc2?F19XO}ǜpaoTĭ4)GP2Ycb'8O4ڥk!Ǜ;B) '%v "{!/}樶oKfBcE?@._ږƊ3zDjIPGC4;'UjCe*T{=」F< y#]$w_7s{ph1F1ISʱFF e"5M'0 HC6ǁPhW.9c_Ŋa'AOzM ߒc7exɰbjK uxYۧ:*nd*+]W&wy$DKfxk/ |i"Z+Ia y9gh:q9Nc\xRMJBqQv%o\^s?NqL_/^!"4 [ Ꮳ ;/\Y&f3-ߣMw6 `IF46X}[Í?ڒk5bD)t̼iJzK5:.Y 5 4|)+\Xfn1HA uۘ "DkB﹓xL(mN4/No5!pg;wy0,_77os~& S"Mey/1/ے^JixGEOx5ɭɦ .g(AFu{,ri>=|^heai; ԩq {rTma:rCo~R>)JD귽G{}  Z킝/f_ݴe{O)W'"&ƾ丯3?b/ɻu4G`&\ppnVFⱠ<ωvuݡ#PK 64}$`Q^-YBhz]T^YJ4*Xџ4ʒg;p];sMT]^C4(D;e']%}IUd7 W4*ScV^h1+"@L(]tP9 Rūm$Z*8"ONMfv+EVZsW|C~&qԼNijࡂoi GI^3q,&п(WS? ;~z o[KC:mej](`8Eq]E|&>Bw[u&t82^hq@d#"zCKBѢ,ޟ}-As_i TΧNJ鬟k2jEJpNpt>'­JRtF }gaB[eX= c9b ԫB]҅|ߚ..ۧ/Bc &>"+g~?K._*pR-u'X[.Wc$àœgc&0=l.G6L+խA׼RfYaI0a4 Y8GOT(tZ7j"=OPofq֯A_)N7pdŭM&Okn :u7{)t^V+!<8&+oƙ1O'nW9ۼSآ-?ERJe^V,g"@c*dC[8䴺+e /_z7o#^+LzT&艽(klI (_%GOclnhK$9D$H{?90@SIs޸UR-t92'>|)2 *\~Tw|abodv0v"Ql.&Ȝ2q, ^UGB*dт/.β'ʏ|b9R>_ M .ec>C~Mjԗt#lMV̬ A"44~PZJzq(_ugMligˊjzc&Pm 2ޖgr([bXvd|HJhgzͣ AB/+׺T=,J}nPV[aI65:zck ۸wF{Kc|ZE浹+:q*7Q=(T`ҿϭ䫅0bF2s@/"e|24?Al =4/9crC'{Mm^iC]0siyI]/Ҵ`浪{@k# jqz^7V`Fkv^ݾ\8~Uƞ[!-i:u>dyGjK,7چ(-c4KBuZ4VF2}='sb|[-gsE{B) ~᫇~o9;c1r"8U OQfȫ9("Sy[cѫ֙a&eiJouq/Ns|45>Ӡ}U25<.46YdhRj^N!ʳyu!hi7|E2*!ˆM&N m)Rk>o?c0k&ftuZ{]Ԫ* ;{ ?^̫FI`̬Q ڪ8)cМ* Gx1} GBuCQk*n ~3$lݬm*ݯ9n sO m.K 7tw {!U.'7n(j[K:%“:WN1*؞nQuӎؐsq7ǝt [?jh_6%C:;f2)-ׂR(^~dIcZ7t. _y6欞lRKS~)rYy֣$87&J1SyA3e7CU(j' c"o*}`4vl32M^G ݰJzݟa|!Bx:=NTjh#dUd /cHd3%O`*Yd$]c1| ѳzXqZz˙ ƽh RBbqv=X%q2C̭ߦz"$vs͊u,H'aۨY/$dY o9a5kTy汲Š̀$isV~ ,*˜ok ?fbC(~Hӆ+Ѧ0%6hZ)<}8kY*QvQeͽն~5qHzLdžs[s-~-Mr EƘxZ=  ދN,vDRGo4.z>)!j^ tp"ngt7;??w !RgwsݏiVG]P9cJL2CZhR)YGپ -$=4xY{{Q W]:!/wY̻|`h*>X³2B}lGwBK뤋蒣-C1v\bѫƲP[vs#/5%!>yN<>bu{PASc5$YFUʵfX:GѪ&#s3t|⥁>LΟPf[џ:>}[ͲL3#|b'b6i(%\#΄+V2f3J|^q װ C:vǪz|/ JD9- ٓ=&U\qY o(3ܲ9oĔq%b{X6֢^\sV0eߊa#`1='釒Do5~k_Ó /lp]r!C* 9xQz~sxnmy|+3:22م )kRd<@+5l70'eܧL:)xgsykCEX1V℺Wb 5h]e춹-_=w;LG}e.F>&^fGRD? Hcy_XLOVw`0kndËwJVqEW!pHp$JH3udG/3ۿ1˸Ν* .8i;^ھf75N d9iV %n޻%gǜU7sN"6ފ-Z2]FE_73 ([aߐ\Qo,x.wk1O9[kgyf]H\DICkCG.X03mt}hQY RUz\z> stream xڌPwܡqww ݝ=sLr-ֵ⽲ Pޕ `ffcdffPrWOtvrBh  n6 '/ /33翆μqcw+3#@O!lea ߗjS ;=@hhjl Ps0zOj~KWWG^&&Fc;Fg Az%@tv*hl4Fx j@H`ke wٛ5y#?1 #˿+Ʀv^Vs+[ @IRӕ`lod7uc T?:[90XU#_a@m7sڻOh ?õw/273 37GVNn@l@"2 +t=M-J[T#Tb:|T/gaYLV𿣃@`<̠c0+}І9z6{L%5)_'`pp7?,7w,K%Ps4[ 1s0~^]_Q_2t[O?us݀&?4rZWc-[H+I+O߻bדt2==\@+ (ao`בrpAa]%01;\$?$q~#no`q1$#o `L2;I7q@\#E7qQq(F쪿(oʮ@5~#Pv]7e,E,0.V ۚw(olbljbkbG(wgcS-1?\ڿAX#=ۿ*_bd` JQh]lRlm]5hA/7knGnXA<wK/GK Ԉ?فdL#s\AWTo2 gQqsYAA3w=vP#m\83Nn@3?*bI& 9#pw8SPտT@?">蝀`Aջz8{=A9hbg Aq{q@PV? ޿9"ynΠ6z/;Zׄ=Tx0MPi0,9=!&Tfo8߉$HP /9ihITi}}1Wk_,8'#dPd )Kƍ'Y_2>_)R!'Y<9\RWw藞(w39o$t~1l|t6Y??ytAޢMS,~Xfa'|ƫ+/l#5FZՋfH[xKg!)Tg?wLg 峿u}r+wrV3=k (&+Sf˷:ڧzqsS}L  9Kpm5\%O ^70޲FW14ngoz/ۤBFk3r(DRj2aӭ ݆yfhdt5O''QP:YMQQL;:5ytG'(scdz>¤Z:ژ7F*VdR` \WJY˕WQnzC-&p[;F؛_E63ӭ59T&z0HR\7~,~e5Lѯ#~wvޚDL4I~ÀGB ]T1U$F=8Gsf._Nᲃ,>cK)Ƈ"U*YHL;UJ@A_v}keDYuslqr2߸չDV>} תIxֺܷXp+#i1'*V~)rTiag6Nct=EnMڦ:cx$e맺L!˛&̭W%"@xoFQ0İAW%4K|?L_ |2ǁy,/p}@5K)(@GPpnMqb%1F>96auJ>%Ub2GZ0t~  ^IUB'PXϟ hY,<Xؙ ss:˶WYh>62n_ ֦j*?戔4 `n7<`Ayy;d 4ɑяȌjWzw|U\lnqJouEDLMS;W3Q̠&خe#+vi?0 N=)́A8YzJGWLk90DZYl'2;D065!$׈@>Gj<^^U5TA%/-:AAc"jM}zW~RD<19lm@(PQz,JԀ2 %ͧ Ai#b:*'"9*$*LMeEz^C(56)VUdaNM!9lIlF'˴^{mg`b%Nj**n(TbZ0x84# B $xW~@GkaA 'MKDuX2{@݆|Fkw;Aiw kbb dj2m:ˋN)(O }BqyNx;=0ܷ%^f= 9#bsZ^dmrP9ѧH1uaƉ :n-f͘ !aiSзZ:PF:,5~(r`)>"S. ;DFB4Q? A0Z:/F2C:TV *b ~g B Qrmepf8 F$.g̨3q#w!IJ͛1PC<XDwLԱ6|*z5h(0зmFVBBO ^uޜ|Zq?HJ}rgY4rsg .?BNU 4!Y(Һbt42xa{Kw&*oc#Wcȷ .1YDd \NM{`!0#Q'X>}9(\({-^zXE,ISty[FaBBy@*B"FvP1L-7y%-n !Yx6 L#0;$J 8Ϝx^h!Zg l)~2܉܁syBO8/r|o4(ƴBo#xqLyw$ ̾N˪Rs2Ӟό3RE PlDLYl<>PԜ)>U2AObAU>8 JȒr I<.%=N sd+j43w;9'9Vs&6/j xU]-D~}"OMСwZʏ^nzGmdt13: 3vtq@e}flUH$!Ġќɉn =iDx-SȍJO \BX[h){خdĽBQj@]/9q0?Ȇ%M)"5SػоSPN[o8a~8+:Ӂ5#tJB$dcXfCAwAH,jjf7`{aF4=} QhS2m8\Q5z:WdMy B-uugj;}:XM ܔKœFj4MCZMR+m ._0fd,B uCB&Ec*Ȅ榍S39u1ڕrAj{W'f‘s.ϷXL-c6knIQm+; d62&| ̜q= Hйd7BfԲJvr }OL͘([gΫ}(&ؑxZJ>C8)Pt;R" 6}E}){r}UaF3-pQ_.F!1˿{+þؔpxpq ; g?#< Fuzf/hlQux0uGD5SǗ[H%Ჩ5);}5uCᆅ#&̔z:iF_UVdPӒ*y-l[(A pXέ0%F=buWZ(Sqc V|/1NGƂ  i3= ,)z$͛0 T!BB8a8gr_Gu[<]gP?I}3ਜ਼C !ȍjg1^~M$}hJ"2o"N]֜5pyIM|HI$c]%YQtE#J nu2wߕ 7mƄ&ҝ&Z^ {gfӄ]T#I*>ä,2DSQh*D7]<"I J,Pŏ+g,+6OlN&'O G]\x&"~aA9f8P xI&g!:⋉[->ɀJ')yIfј&BLƵ%[t-0*"-$v[;\c8)Q۵AEV1Pp1=r&T{3`Q)1Q^p\QmXTFܬ5>Nݖܷ^laGI%6 ?tkT<8,1Ok*Ӡ4"FdžoV= 5=?Fugg 3Wq'+0b%ɜDeSBU&->o4ҶW`Jjڛ+Mj(C6W902PqsX%,Ω a鏳qX2I[ca3!(hddSr0}jY: Gͤ''Vo̹3uD&}QQ񁑬h&eѬ7{aANھNy ΤB9Tc }MsDl s1NDBheTO%(jO2z}+VC1:߿&qTS)r{(DRI! l)( J4.FlTkx_=1(!5qٴrױ!-`Vm1\ ?U}l|˩]-̡ܖ5.e+ 6gWLeSBq'蜍0N|zRmj߷w* ƾ;Iǘofr\LzWr74$ص!}$ht>O3cV3d6mrhB&-@FRZP sQq,NK|W ̞Zh5D=wK 8M2bc}XE6tkwa9+SKCOC!l0Ax_CBL!߃G^cM|^0ab\HHI?. =<uMJ7<2D˳RKIA5hj7o <Դ~]ށw/囥O3Đh-|Ӗ`xR*ոO}粴em\/ȝ2\ ٰSEڑJ l _?@fDE R0rEXykoX_p[u1>n ݥe7 UG"sb{zMtǕYVe-5h_RQ״g.16Hf຋5Z$^cnsYF[{%do$ I]beLKZ1`_*iuBRHCpyJ"N˂܌rG#LM ͊MO.V̀ӀF-T穕TYch[35Ю#'Md`R73 ^rq?*j0ToWG]893H"JDp SDA_t=2!5hX!4)O|h_Lv@VoFz[hW W<e>o%YK#<6y"̄ۋ㲰ON _3Ħ qn]tĜz,P=˶Nxݕ/R&k55,YR;IY4Q u0 C>a~5hαE?/K}<)B?EMc{p0\4lA\EOcm]%qM؏p3ԇ֙nӈ&E`/m\sob6#RɯSt'hEAI<0rm*+'>7K$J?1AF/rj](3~3~x1>I)b"UAA  6,W/J$]>̜0x}i_Db$w V$+o2gU[ 6-LtZсU^`*'uDV#`wg}׌DуY ';O~29I~N6ή;5۲kB,RUd䭕&X^Y<'I,I!I4=Pj OНVP""?G΄1&fZ}=6AO&r<l)|``hI,P<7b ha!'D2+N*j㋱|ϒwǢVJ6#UY*vYc?$8hkzSP>xYYHP7, WK ?V93 EeJS_ ;a-7(ډ hL^&,yr/~x-t;%*=,P { bjSzw1* z_X5 ki! >7JD-'^?V&(G~DRpqbݔ$;wnshvf677 9HhԔ0aKb%*\>MkY^VqcU']8?ygeF!_qqLpOyX1C׷_O1P$Y6+baYZadwxwC xzFixXlJ&OGy'n1&N8AwvbA@Yw'pj)+,MrdO0_׷b|Qt3Ev_)OM~}ảjb vpp&!TOYwSw?IS搉"."i7!؈+7\idiZ$`e:xޡ9(oӍ}Ag̐#U5iLxB177A`̮tޭk{xÊlo,fM4<+F/#F rWI &*0t p¹ڗUDQ2hw]>O~Xy #Qaw{],ͣ眸+/%#x>.u "Tbzg8/`)|Ԅ&QBG90ktEHOg|ƈf~ mln-ҁN/T_ )$wFʫPST8F$#nz'GA[fga@֊鲀ȥrTM'տ"] "  #>P~ ΀  P(==e Z2nܖ1p91\bK{IH[':fK3Y( R)JS \0z0XsӉh&(W"Bv$,W_s 9ַNc3˯?rbgx,otF *I#'3BB\F1Ą;3^`u&̷UXw9}ɽ3 a+S>Z}Du)_u0sP91yop̭T{JªL{~" Sc])/5%|4uOyYf M[EI1.ܓ]hl4p(VkJ(c_e!`+};A -)7&b.\G+tH+ct1{b#D;STA6Y]DW s)ESv]vQUBwKh&QZ9w=bwK !qGYS{0!iKh(_La؍I_)I)2J/aDgD["r欩 ,K{zf6}Sm̓ Vjlݪ/Brk(m)V4.ܭ>Ȝ\S,O{#c(-1*H%gU NroO(W޵N\~t#ftHH~ͪn9si{#z֭ Q'M4LT_2x9v|4\>l}sA_4]'t ){--{>Jzx"9y6F.l44+Zq煴!'21Qʩ~mU K5/=5 zviA~Fk~- 5)ԢYMm\(W֑#h[ᤏztٝ y.rȒ "w,o ? eIԇD%3WJ1/aG@c$?P;zm> I]KR[z'.Pa}^އ8x=ՓΞoIʠة)aEq`^E{.xe~D XbǙ$>6]x\H65d4.{LN2VخrY6 Z}bzQB~;<){wy/H!XNkW9puRVf}̎hÇ^hȺ1m]*XJPN*z$)3GcXj@1 6{/G֋Y.ՎӕY^mQEތ} t1n@\:~D)\H8E2r*^Ф7:'Ăuua-uj458O&qÉ}jNYhܡjb(ceg,Ϥ´[͚0ֽ~ȜB߅ʩɻ%DG?ΰ£4V__Eíb]H d&dYhBu=#(JN}V>֋5ߙ<|$|"_`65Y1d)7-2O7Lly2F#Ci6ڃG/G\-Um<.x l5E!9Hbvnn|g hvl9>vDkͮ lg.[T7]%6p*%ދ7, t<H/:Y7n;H[䀖3@>nbw#Ϣś\ {L!r 5Òi}p,ņ<*!*-Ǜd Zە+o,tX=- RʵԽ zb&\Y˻P6:b%@$}WZ:Ԁ2+-NqOZ^RF.w[ ;czfٜ(m(3Ui}eև)FD6FI~{\d-k k,cy9Pf&v'.fEՐ,4 8?ao^l A ZBst`[rnQW\(Q4GEeD6]s08Bs~$}C}!Fp0pAwČzTMfZ6ܔWUSTK3uUDnymmcJt\*!h7]Ϯla8 Itup8=ZX=ͯhZ\2qH&E\bu|"W*90zrDgЃ8΢;:Ńf~\SUL~ '+?aJ 尊DghMyP:> WPigp׀f 8z"O M?zhDEs󭯥2"2RΨ烁fQthpOSi|>4fTM)=3--nSfƟi:%zuɚ$Nqwwkriϑ1ޑYDz32гC|&L~гjJ^h1]~_=,ช8Sͯbعһdi< q~u]Ԩ@ǁ*5^rCͻi2WuȑFvE%tM)p$.Vm]ɨ}d{L^z=cq;G3 \ZK͢ }XAGvXɧxHb8{X,C?}r*i[̴ߩ;dX'rk6'tð\Bd\{YPTN+gm%R@~(6+;qƶQzҘl)\@i zƝo ItߺH?SmqmB3 L^aqĤUȱ֐wfy`px "-TLosU6 ##RdMSEGK1 `sȻAx u?Xy{CkȵZoFjԼg$/Ԣ>zǽ x]F#"De![j[Y{Z|S_W16,t"fMXRc>WjcO؆HD;҂%%OEJ܀;Bgra@2#ՈE9Rе }bfUF>56kCBwDVBn]@Z؃S .ueWy.̀hn[ 6 &Z ?LefG_ivYs"?/p _p(Cyd L0s[wUT)RAr2䜷z'lߑL;>7f-=D^^oWsFo3)YK1@ld^,ɅK&Xciw#+4M2"61|G.˾pDgA>=[ ]lޗjN7g$w"MD(cH=XsOoP9U3G!)xN,ޞvC~};ʑ<"v F|0KXԻC5^k_p7W0\o;ik:AF&M;ɚJDV'ly*pn4)o7dP Kzȥ*؅<3%]%NbK"4]yUX?dOs"H!\Cy&*s^kxkrŗFOHD;^n' vz$!/G\yR C`DڿtMPtsU54HJHy=ܲhOʍ.tlv%'NPť7rq(38|O[$SĘ42P-(.Dab  x* O zD7zn81:z97E?T\D__w)n`M.q \’y|:'1Ȥ|ej4εݼoN? ax?oSWl;2_$xՋ=1Mn$]ĩy >Cb}L9]O `PK `MAv.'E kV&L`ן;dܵMzu@e)䡬 [[1%l⎢ngm&g'ag}"-8knX;[yڥ_͇DGi /9<zsohAo1sy"zۼݛ([7S9$W3% 'Y#ܢ?&?^q۟١T#Hg~)R8夑,<Rr4J8\=|斋7esj*jkn]wAZ5θ/g,T&GG̯ v7E" = yg GIğJKXyIӫiGkxYng kbBiQ=sP>-?cHfMʀrw\|wM1eOBz}UR.b\~-]ۼ("ܫGwΚS0Wl9x.iI22 Pë6+b n0WArv-v([?KMTJ8]UP*֡ 4̈+ UdZ$\Ӭ4a O5>Ry_PsF}4G~E1/3R!5dJl#$Y( m^X4s"8Mڡr;,!X1.rih8Ƃ^Tk-Ɔ^k5\ۆPXŊNB)81'{DQU0ūY0^.AW0Zx(*J*LcvS&oRAё RHpHͨ$2cf={Izuɹ~95<N_?g!suoPbE[ADIHk;\U>/眶?3([$] vC{AV=;KV%Z%#ʹŃ$|Bװ,۴ zu%g0K FD[Y>ɸNG5Ay2Iک:h.W1sv+˄{CCܲ=;s@IEIlxD_LNWF#יȼ3$*gqƀ|Ӽ/KM %5xI'Bb|X{H9%.9c ?2JiN|jR;ra_$JOS^2)k;T*B!?vAFyXo {ZM}#5,~DvDBt -3ShvU!mQ_g ªSI`zCi>"a+^w <:.L/g^ˤŸˀT˼ZynC߇/z3}.BHϨ 1*n'Hk~= kH1 #8"@8Ɍ9@~G*f 2H`{|ei9%! 0+8gDw J's4n5R :)OM U kHŶ1UKL!cѷ{^*}PbN),4b4f;y+22YJ@@:^:0,-0+6 o$xi[I.0|eßjz9jh[ήw6zHd9"G`_i:U:0EZHC[͇J7D ת/5F1l+y7s3KYnKjpYh]^2';up~`w7u+t>Ÿn^gfGX-+t뭐F nee/Iz#me+%oU}5|eHD efhyclaӑi \6&jUKZ% frS/%.)Oek`v(~꨻9&>@hH&- :ƍL.nIޓK!ȘL+Qn:QQ> stream xڍTz7N LBK $FHw#]La#6CBB@SiA>| Zps,` T  ``І"l! :G'(&/)Gq/#T0"  @i3T N)#q?,@.!!@ ;# 6`[ AWfQ^Ņlw~t"l'3a*gg O vP  8j؟ py v[X07(hd96 fl;`{ߕ@}dG8q8Am+e`Rp;; U4bq?v7?7wy0K_MX"9_ H_&"?2ky †Wxm7{oo}^p{}/vHǿ\\@KhDCw A~}g|O/K8T1UgupW;? zwu0"@x*@?kuk c9 2Cq#]+[,Am2,qOTɪ@,H* g {P'Y+RM?/-Q;A)@v.twepol; n뾸`GGtO#n>>!ZB\3#]y_ 9e~#{7rFrBAA ?/x r y=1J tO/xר,Oo.?B,f"/*%(]طFŦtY=>9 /X*RW%:-m0XPtym9'" mO m HA|l n9=ŋof4+^OG 7+f2O!{`~FtJ0}v>E1vG :0X9\NNOn@F~F4Na/m Q6};Esbʜt&qºwZ8bs0Lϣxx[>_jc68ݸSN2UwS{MߊG#d7W 8.Ͽ6-_t Ko){'MGgeG&|z|џF_Q^ TymSoY SIYnBxβKc;J{eUjۼOh6v=nM lco7/XQiL[-XMAh~aVa^,2vStytNiTs0s{\[+wڧ7AUm:2.e7QhyC# ܼ+&>4V*,䇴|Jig=z 4mFzn*5 JByp绂zI:(b~X0V'-U(Jc?$%4D=)K+"?NӵaݰXg>#xQ=~|1U%ULjI(FUX^:Wdzht28#:~&bʌ/`hT9ÍUi(kށփpǃǠ[t[.L p^-ǮwCTb8?<ې&'T w.fB|ϫs/V-p+AOPٟg`"N׈14& 'fTLgO.M+,KayP즡77{~.{\?."8h iNb9IR+ͶӃ}NZMSOFkBo%\=(JȴJS"vg`CnYA= +&oxls/\onSE׈GC#{_NEӒ|t٥l\eqO_ssv5T)@<)~+&9˕/K*0/L)wMQHr|u(ta; OpuW@h-*oIzz#W^`kotX7JXzVfoc<f&8Gw~ϼ4ɹaٹy%zL6YB ⃳]m 9VCL]"*2TRqSE5%1aC4F*ٍ0ͷYZ b%]+IÔrACIa&ĨĢ׉ҙOЖɎ- v[Ė0x^Io9Ǘ.qz/h Nd(})p:g%a;4cCK-Yom周#6'52ױ*p|R20K@-ayv]?kRȊ\][ibO,2BBy@v%\s8q'\d3:bitt{e2yx}W9F:B2>\p|).p.&>#= =lȠ~Xt܄` _l<䴩0&&h.m`s,ҏY> k$N_:5tfӨ餤~p]F+ilRg#vA.KV o%#Pf1|quXГXQ7\x3q(K^D]^MPֿEyG^+OfYMEoRG$ĺRLG͕C(dvƑP7 ah!S&y ،Aw+?7U_[ {YԮgȣ*vѴ#" B9=1 iJTF9ޕ[gXyX$9NɴP%QK7 Bg#ZsnGYeJL#i[`Azd&@/0Û&"P̝G lSaBBt,ƀJ U9)ySX8b"`C 1 iXmz/yS2(M`&V[ˏ3cBB/Q@unn86&YEgaUuC~ GxIx)Y2j$zK}/L7sc7 D^lZ8>|:8Nsqqb[o~RtTib\ &~3,^+Uko&ݖ9Hd3JU-rƯELe?M0U^aLV;#ьn^&)߁]q x ykϝnm>Ciy)Aw޸1 Aqt,{b|W Y ƛ2iaVE_׷OjN.39iu ?Z US'弶v; ?XpKE0+7΢'sĞrsr`NLQ6Hj>a)+Wvknv'{4‘n*gTHGʣMPؐIVhbzyrOq̈>F=2g%',2G6k0_[]aHkw3N.k%E7,Aeo܏xޝ|?>R̗g֌a^wtb٤ z1ζ<+մZ]Vyp 9 TEh|GȚe,x7. 󑺡J@㦄^#WVF󺁍hS7NL /O0:Ds̋BҒ!<2fӬTӘ!91ٲ:S>rBO4Ϊa5ؠ~6;nSY^uϷӶ ;@ϥ.Rԩf1O0oӖh)YZ+ tB'TZoLw§МJ&=!z67 Iڄ \ZU-/pC tig<R[ɂd]i #sL=\S@[mSu}4ԸJϪT hc$Ű,au-{}OQhT;sݠ*JUVt1Vl^3On>LWpM}ًI]լQ )iEBϖu&nJ|zN҅ȎRN_m5<NNo(`ɹCthIH;=49j&o!$1Gh7H]*|͎G ?ze~9%Aq/to8/.ͭ.;6Do Ibc:fi:F[4b2ۆz s?/7(Lvx><p'ڐke㮙! pjH1*9=@N+%{>C;Y[2:˛*|[V$[YEYi=WLa+f0}WDNy40y!SoWA-&`kfjUŅrXcahV?IbXG&,a5aT1vn\b!JđxIZ$lAM0w%[fK(c"zͲKAeDaBdm*㸅[nˊf/?wƇSS6̣uwP4nNu6XqM^pҍ8XE&`o _+Yv#ْ/=,|%.Ȝ.ս1bvڗ$@C rqViа]E]j uƯ'W&978ݹ1CU(8F#}ߣ;)2J [( ||ҭՖԪ2V-7*=;L!yT^lZ\)]ZWI,gS#,Ht]GLbn@Nm26?Z:HwCA'QUiDk ոB(dW{S^-mV<. BgN $S$yUb˓zHacWI/M6u-RjK?wmhd-<пuot|"R}`^60q؛.tZ~:.i(,(i.t2!Όs0WΆ%$Onjz1`^ryzS}gLV;?2;*7𣂱v#Z|hh}K #P^a-^puq/'Hp1GiZeOTR/8Uԉ6|j}fUĎ!`Es&WZ E[[(E]>W|~ײj'jC>>YHR`YLDQC)|`gӲS޾bFG _z(^ںzge;r,n;jK7#T :4Fr3(;BY Di!5TÞd;u$+&@!0Zt޻XIY :|M2Q!"G/3 ^-}ӫbɦʌ>|͆DL0~ (}eH[qVGXY{ں~O]' 18> O*!&S0H[t7ѣ#W[9r!d~NubS>{ZGgY6fI'P.ѐP$+DEFB~z˿4udƟo1ӏMz"q33+s8%96ixecT7v@n3ny8V9+$*u䃸vDsj"I08{2G:]LM;~c7ս[᠗nl`I4|] u{> stream xYnH}߯b 2"^.i % dd{EԒSKݧOWcQh MdRi`Q+- ֢ia6-"9f4`*`0zIV2Z<0Zj-pҰ ga ҳ'Z'  KdRbY>p~)0rLVA4!V\`6Fk0[ ``a`Kh0 #Xs`& A$9h,>C)rz+EbI"a"SD-V!B Yhli:fb6FfGQ`v̞dM;0BS;J:' vRCZQ-SE(Rt<ɇHkOM6o3I g#PYD"IkM:DF#٭'3e6Bl NR& ?,욽_f 1sVae?4B)2!)r{a Kp~{ז;A#:N9pvq S !-)`j9V%P,Hiͣ3\Q+]#mt؟qsDZM2@%N2cB:pJqi{*r%8fֈ9ɦ]0Y!>yܸ\q\_yt.DciN/˙9ebv;NK&✲9/%81QpzEBz~`%Z+recqBqU33pӓ~<2-|Ԇ$YH?r9U6"hm[;p Vg>̋glڋ@* e"eYfzYo7@mŶnWG&/bնzڻOqU7z[>\]o*@C^˨RIh &/̇jJswЛrVHMSg2ݺ\jS?Ho3NGtenUu*%%enӮdbI{oQZ0TocW.m$ǫ]j].."Շ]HqWg[6HbGnyWuԽ#M t &3@̀-R Ku3=N|jçH4/ K6Z{Q S S}DJ%[_2{H03$Ÿ\u/)3DqsnC1DLn,"ZZlS`[N72Ir,"x į$SYEf2dj+)&܊>Di_MG{\~oa }_W?29=5V gR}J'y3> stream xXn6}WqHIiQk[$) ADm{dIt "3g 9uX4dBo%Rxk!ě"7BY7oi<J 㬠8VRXo%SEba*&bb#RnP,a'Rj V"RSI^i$ =X)eah6S=iYf])X_^ *GB%BIͳR ⨑V$HZ ee[F57!hNBМOTsK!ZQ"ZL&hFBh6g͆2Mh(!,!hN8͉М o$?,r@80aLŐew< P6D-ǚ4{k ~8(t'v.Cq<9 ' ,&3 KHW_-.މ~Y6uYͧ\kqmqSo ¯i,+qT.o#|ڇƟz1,˲eowwfu;maPeldU*OF%J|,]]̃4^Jq!/:aǬ|/Ηg=:>j{+:޷3Ż$qW8X._*R&- X%$oNxѯە/ECQ^kuVU7~(V3>'F^q$71R%f|})f̴LN+K?wtԂVY蘳mptl-wSYbYr9pe쳧;$Sq?4jf:JT HzSkmB% FkmKvڬ_|[{?KHH1l$<Y"K/oIPYnCHIm}r%VY.Qp%yEE76 oz.Fdc-﨧o>Ol6̳uO_8Qf]!cyflz[ôw9o5R*LkFTlwqRs$3hէG |[/,tʰ` mb5ǒxQj3uX^݈W/rmQs߲|]]'}6iPȝes;8LC/eX+T?nn.Cy?jfsFLa5jE߾y%4!3NVG]7<4&>У8YOqZ>M%CuѰ:cu~\ OqP P VOz)}?*28NH7t?#&J"%"Ca92q_ LHdI# %(\/x @R06zllNH/Sr*RJ ^5~RML'h $ug,s`i>jd}"ܶ5}#|'`p 0_ݍ f3Ā^{mT%pv̌7QXJ€';Ŗ00i'x72zkw|?:PCb ~l w-sUendstream endobj 479 0 obj << /Type /ObjStm /Length 3557 /Filter /FlateDecode /N 92 /First 843 >> stream x[Ys6~ϯڕd**>c:I(PKrۿ~uvWm4l  &I%)]ӎYCWüecRIzL5cҺL025b2R)i-Ô2e21#T*[RYfVLlEL{3l:%SF[0u@@#4(:Z``G1&w ^[݇>hd$!qV)ƫJ3g `f1mzh2 Z0GK>#4'{BJc2E,Kfמ:,X X4 J,;!oˤ &ٙ& DÆ>a0HRMSe !1IaA<#XM 2Z&ļBx`9aKȲs( X2iO9D@`uACP) H9y!Rco%{U׾-z|UOIRף9ʋ%凪(^XgۼW[4OZ,4K6YUtugXue(~\*],K~,'%iQƒUg1гg_ᬼl`'2_lh~e8kc-_Ԙ0yo_i˼:mTW49Yy0z;xz}'7N?Bo!5צ Zݦw'Ŵ)zQX>w yn^%GeQ4<2 ~k $)& N&uPQu%țHkN؉*vxѥS05C0rp e)\XOx!*);5.X!HAgfpCHPfG8$J 0L3dQI$>$o^c5˟_AChܤ!٪dwTQA’?jR{1?Yr9e2H)<ķitG.\PuSJ唂<2(!.&i( r& F0H5Bbf`)I!S#+iQnźSJLrj!؃I4v&p rk=Vv<uՇ$lBR@=U) 6+PnP4;^pLy OGuG(!6'aSJi`'¹)8f_1/L1 א!!9RsVs é"B8po'??緻Xkxx*ƫWiQxUk?#h֣CWe&95!:E>B Ge[OlC04\Nǧ</ʁz!PTd ɈHY 1hTNnV˪&wu={)-(CV.qJ *x'r3ܰ|.'n(UuX҃{Ÿ7DDq8VE;B^zĚ\ [ ryO>\զ*?FTrESOXrڔoEAbU->+YD h/_N'ȪQ>ŋE=)EFnCAvrARr0!ё"iW3-R!Z# loZX6-:Ӳ;.T8ƒfּ83Ŧ-~ִђ,LVZ݊&Eýo7in:/q>̍V6Qmb3-OfzbQ:?DžeG=Jh/p(l pxDX ''H WH r"Gkܴ 7-{?p;FB>iqWQ>QC^7&ܲL`mءϛ񤂛=`Ps/$1 g!lk So{68"ϯbZQzlz#Yvch7E5*).zO]>($mmIKr3υeA֒wenI?M*M49*7Q=="xeӌk{ܽW`F40Sm=GLM5J:oQ6h=CIKpjykC@7:!WZxQ:DVq@1g{ kQ mkR&hhMǦ!Zz")L-[i.mLLJ,?WӭJ;$565Py7T_v]N#ga%LH4m#_Rp%F #,v0wiGwH,`HUo0XVhӆaa~eK t\vZ_]S̡ I 5(:cOx2p W(Baǖum"^L"1l ᮓeo~?[,B@4'q*(Z9N'`EIKDžs49?g+雞`^%ɟɧm9>HO-]$F!IR;Dq󧷐'7lr+N'˥H'tmFsj7A}N+_VŁ2[Pa4n]8ﹾkoW߇kk܇}38чyrήv顓^t( {s{MmJpD-Sj`,KS3-c<ނ6bWP= Piz==:N ]'2 =#L#n^J"<`me|o0n֒|oz=xCZ~=Fvav?2`)`Av^q:K!L=@1 L/UR6,`ߒ:wFњ!։X^::<:{{&yr'T2AllɎ$M&]]6e|.By1ˋf W:[X[dnfgŕc+užHA-Dcfg#RuT,REF⢿k.RI;훩Dڷ2Ũ2ת+gQ7@6*\rm"Ow[5H D뫶V^_$g'lٚp;#mr\&dޑ4/22ue,JhŠ̵endstream endobj 572 0 obj << /Filter /FlateDecode /Length 3609 >> stream xZ[s۸~ϯIZ AȝMd4lAY-؛L{n An 0=/_>yB&EZˏ:'Wg/4KrktW~5zwi lA{MuݼO.+-\&p:o$Ϣ:ORk@yRd9$w8Æ>5ʹ]~~ z/S{mq`ٔoOm Y,*8Mh{嵌{ʪW|𶤗->l0[90`746.҉5O YhG6^%[邬soWd8a٢?"N\ #=XXUC_˪y_ڤ9fBϴ< 3ЅITop NFM{eRq&ۆZXP5_;81FǢ#&,c\5+0k/qZq3d ,y !# W̗)9\r\-J,'o ǰ%%!<=-u@9=AdAOϓ,%GkUa%=-]xx,k&}I\3z&.rxW6oM-F F[f “,?FU^F輬t%qnt%.z+VNf5@&]g~^Nǀ`o|xÒ~c(7)[S'{yERe3^VbWhxV{QiRR}UR6rm, 8;d ̥ێALZpE?OVU:j_25TfNGblOnCM/BKQ3a$~F1?JSy'S~Ys>L䯓Yk%z"?fb/jZV )yzOJ?6[pސ @l۸0"oI z{p]5:2܇H5h񰌂:@?*=tFlWBG4b%S@+& ($En8,ciWiR0iɚ$;mM*VCմB[OS?`- ]$%+)j\6b^shij!"};*<,trI7P{`,U6Xw%(mh!3-x" تm:SeH+펡pdrZlN:md\QUyUțTn RAf3VM IeQwNY`sVy*.ACaRN(z Jf oХP²M0W]@8 a73`f'Qsݥ ⷷ9ySy%.Qv:&_rN+R{.{aa0!rFT}z4D\ Hs*YgAy HU"Hw͐M2#iea(=`bD\n+"A"b׮DJ 7y# qo;^4Ǎ RF_CʖG 3a5Ԏ IWrDby~' BԸǒoN$j~Iyl*WM0ΰ$pU:x"]D ujYP'Gvn@Sޓԙ.B煮Fb ŗS{@ReM30QEHS䩋h9쒔r"Ӈ:մU_}+zIzH2|0``9id_x~!aXȹ1ƛJ#dh9 HnS7_GT^LRsd%J*OЕrH^-WۤP/)krρ#e5E]3"79'7x1Hbj@il2s8Jfn.^Iz]@QMfSYǞNYnʁv.-[,L&g)v̋Z.L~cLЊV];Iؼroa+H~s,"Gx绌؊Y2l:^uX]udu~cۖ(󞱔&ꩤ14>D;رX1W91 6l"$:lcsi6;@{&q4 q}-i,$/jt5\눿ao:U4yũô;s}2D՞O41Ч2cWFJv\˗ee]%dDZ+g*)H@w fiQḣ(;6)ruN݉]ح;`ƴK[ M"3g(#kJ(Cendstream endobj 573 0 obj << /Filter /FlateDecode /Length 3593 >> stream xZKsFWKU0 U{Pd;ײUd'IĈ>jk[!0ϞA:|K*MPˁmbl1\ N.?=| &sת\)W=\a;= c99[ndol3A#,l {yRufnLx`a4gғT~UqI=x.`憿.:UrsR_'4QM;bL$w6L78w Y[Zps͞nodu1\ϥ1 Ͽ/p@.pRZcK~noe+{?Tu #2 4)qa8 ^7Kv>IHl q#HUX"썔5#.;Q65VL4~ʰ O?e$Ns@?Jw֠4QYu (X3JQQ/Hn0ᇷӺ75g#>$}%.~e| }Ħ٭UP՚P5<÷WG<f4AKê}f^dЁ"/yϛxT%.-6+I&H^H1vŰ5cd3ItAљ9ca[Sתo4u$K6%ij_lY(ku^wcm= Ga}X\y:&HAb#(۬r~bb1 M e*jf 4Z8QZ$-{Mkq̞-t"f:K짵~ǧÍ~g{>GF0sQdgHt5:% 3^Hэ@HzQo YMXVuQ*((2 d^JO+7) 9AUF ?]YGBNag6>V*`;MLn&Fmv-\ >x c ѪQfل 8 ITN < 2*r7EeWw奀\H| 'u-  lhY.%w 6 9JO8jB&O/6aLrۖ/TGt454;O".NdK 7aTHcUS!y)ɸa@zJgR,@nPhv~Lw?!iҪ!PݚWAXF>Q2s N1,@%r~2q@B\X} [q 4*ucf5Ů=DA9m`Q3CqŔ)#DodJ a8gh[X9)BLq\d}SmG(΍zOW:Smx⊝,X?PҌӶX]iͪ>U}_9;~$F@y[3_q'D<Z~<'q5h*ɑI& .B%b W ;DޝkWLU(ƧciYX&J/8·w㰆WTЙH(LAҤʎ#K_7< ? Y0"3"-υ<a;QufPl_SSJy#Jr=7$vv+Ј"VYaz15R:/7dFR*ɳ"lbњ71?;*k G!|8 GӮ=RA+`M2-❆M bB)a^s*v6yF63JURYK$1܌.=PxBr>g'QfX_*8VIhEN]2VQV8łlZY4̇Dq:O|W*6ٰ%xuё >8}}Hed|7Z^#XnQ ٜ—?q-Ż3O қN TkwT!ı(RQ9~7}neψJK,zQFHť|,<8p(A 7t@mm]M |Jʑ K},dva6p;aKs PtDqG0G&cuFtBLo=HT.gV^ 绖{u=6^AO? `[$YvEiʮ)d`q:w @ɿ q}h@m b|4w}k@}Sг6_ZsA,wÛCa\:IMQ8J=Nŕ1+ZĞ;PAfʹ6vX պS7g`X#T&THHE̫GK)ubp11Nq32 ~9rgw$wydc=-f51+P4l NV}pU:O2[lϥ)pEE縍NΣ-x$hOTDe)G7oLnWcJpf)L^E9J54t7BvO "{ׁFr]'Tnr⨞\ĄWZQ[eؽOu)ٙhj x{s뢸u) |r4J;nEt0 +4>~ O p ǧT gFbzz.jInC.c~.@F>ZG,ByVO =v'ofQG"`rtcpW)"k6z)_zY&8 ;lVo.1&};oh8^"P*|ySO\e&e9?јA%xs?"m +̖{Ķ'dۛ>_wJ_!Et-9#:~^K~h3 YofĐ/bvez쁿y}[rKM%nn4I_1ʟ 428Zoenf+; K1 3\bE&x?{IuPն`jGeh[f1njmMOɁ\|R'R\Iu:Q:9>&9kB[`)20`uF1xUV8y_qendstream endobj 574 0 obj << /Filter /FlateDecode /Length 1679 >> stream xڭXYsH~ϯp\&K[<$$@%-[q3=Hm yk>3D,xIy' ˤwvȿURtY ؇tq{1nB^.$n(lG\Ks|/NI+Q*,Vpg'"[ϦᡌR6qly\tS#YZ*R+?^b7ӮH4=8ैx[[ T{.s+Sx .dGw8(B8:˯Ps,|: f9Jdx /.A >/ Kxvn_N%*^@ .*GОs)ذzXVBIfBT-)<~ t0S K lO]#PH1(UD!2 ]Y1uf5ڞ"RM$㢲th:) =."vMP.S e$V +x&fg=gjʙ5:aB(8q24^>:v8xKJ KHɾ 2YH$jpJ Xl_U6[|/ks؟6[C{_pi$KjP`ZݺB)Is(gL3S.dG9'c/ z$l XTA5>HޥB#~!BP(>RQ7F|D܌ 'ڏfېLIH)&؇݁'@6lg+Ltп.(lQj5Ʊ6+*4[D&㼪Nsc`h*`]h6!CB0#{dG cxlmDrW.uL)U3W22i{~0&|:\# G5t4i>&C96bh__waN[y睹wF[KLݶduBG޼2[To0&yCY6AuThp3ռX}4sK<̀ƕi7P i%\&D"S\G|Kkp0DF``<ᐊRZB HpDuXLҜVFߦKWC$:y=5YJJtF]_P?D#Zgk|C"H:W!H&9ș'cz֨:=O7&I/(͍בdfL?H6iWѲ۫lYkvHoɆSpXy疭S舔8!we kaXIX $䵇qDZ_F_5ȕȨ*TjTѶ uBnS@KSpFt5_U9oZD+oA/)ٟ_YoHzV'|IQ)XNӭsC{.pmUfm]-IDI,-w^6/[AGQ{3fe(2E4j{Q^gђs{?7; aqe?+%_)=?{Qq*"aSvt1o|[bw{[Aendstream endobj 575 0 obj << /Filter /FlateDecode /Length 914 >> stream xVQo@ ~q8 IJҦڔnUN>Є!t@VU;ִ봇 s?۟}8p㽷( dnDŽ7~oLfƅyhq3Zy ~%\ZGSВWp5Lo-?X=O) =AԲA +1MOn]NwF\. |I̮C{D}]>RJaÀS陛!euFGbցzpF\]_8݈b n~59r EɜW*%ó%Ns QG-tsZL $!lO`?H&.72V32W{F1>Ç2I=0g}w-pYpuf&:<@1z(dWmmaApoV?Vo RRM}J }4-ڴb?82b!$ly7*xTџ1JΕ զ D@N˜ cd0Uh{=\DQ כ %zlrPK)a !ו}'f֬[Y) ^QS}8[8L\:#d&i!ձbh هCעQ$Q\& ?9[.WxH3כ0?>WSsY%(om8^ ~S,"S"& cW{RJzFK%IVxj}Hp$dͅ Qb=C%/0r:]TzNKz;O3cqH9QqIZ]I49-5pqmMJ]!=uҔq]7:w6Cevו"VwOy4bHޙendstream endobj 576 0 obj << /Filter /FlateDecode /Length1 1801 /Length2 11970 /Length3 0 /Length 13096 >> stream xڍweTY-nݩn-8A %\܃ ~UkU}}ܵ⣒* (ub`adʋhI0Y((,{(4 [pDN61Cw< l `app23XyC9 ],L-Bd`af^?jc a-@h^ 2:W j~s'';^&&WWWFCGF =t:M P05#@_.Un0:9ۚrE;r"z,,w,l 646ں[ؚL-E 9F'7'zDCkG{; =#S2EۚllN'f4~L-oljakb(&vL@iM̀Nfff..t36gO9=@vQOGC O#hfaww3_]nw3?INLRNEr <Vf +;ߙ -?bmMA5Ӵ˿@Ew.лl-?C_j#' gk?_ C ks5_gXdm>i'5{W6 ;#3n@% 'c)_v?rybf['|ߥ+nk 2cX988,itS&F[{}Bo)Ꮳ0aqFl&;Io `RgQ q3F9UF9UF9B<\&ÿ{{Z0%LA1|c`0Y|l7|1&F@GW,up|O_'n~ r݀ c ڠjaW Vvϻx.lKs'%oMVV^鑼ЦF;^S'rά]]_lM̰5 _gIS6WUjF:L;ė2}i6rWJ=XzrǾZJl6qQ4`Q8snK n`g #=:6TO=&PW}]e٤GF_296A? BpKh>/"1M;!a f-Kjkd7M(Yfȴ;rA!u lzZFiՖ [(krU).?[ !xXp `ՌEM$%{ 3!){ՙ)S2:c=^Oo4"4mv \.YĔ)gòݫ ["Qp-5o}!FOk%.!MUW\q<-uԑ5T]r1̵TUBB{ 5PRWlQɍMH(AAtrvJzؙiLЗGAi!Oۥ.mB/Bz0R]eZEeVhX6^n .杽T$%̳a1k0[`97|V])[aИ:/Ժ\Sif%tѧmR\"ԤP|AoLyȞUgW0A+Z?:aQ:E`*HDžӏCKK_BMʜ3d 1$'; yNi_% vz~8z#ٽwiyպ"-OtEB%x\/7{^6 +[vH#j߾fAi*IhvRmg0xNm9P6)ȰIl{ .Y//`8h*;1zZv^LD&}!PHg*zd]|zy.q!l9E^sFglTQ1"펯Tp脝PSt'{ LfB6Ө[bwHUkI]nD ,`$7ëp*0& w)e3y|lggt9o #fz =_J#"[鴔r'A Q8s3Y=Ydu•ݢChQڏ,#cʢv:jk )4*?W4\JtYM N8RZhDKUI_'Z蓪{Q]^>~:3PűTG$/LW(v^ڇU6UEnc&{S,hcq3wLc:} uc/qFf {FR-EOW'z. DkEiFBE\ 0g- C͝en&r_tl_jP٩ZxXr ?T`4C)y5- O͐Ĉz3P7c)H QK1"vLBX\`yoVwWiPc$o1دd/feR'۱G'͊C,rx2>ޘNnpݔg{A=c9w n/aVYQ X7Lv+| ~L#XIHQg`YD%̹ R8og9.u} yB*\+O+1f\?9 :'h\f ^d5V,!n.ChN/VQs8",p:Z2EVA9 fxGI72Xv"~ҏz…:H]eeuFjA"qL)6N(_aCcUWKgAVʀ!Z"q(WWkYh9Bӣ4G9eðWms N5LJ5&jn'R\K֪&V^ g_nk/CM-V!UR#?%A0PAYo!qjWp(D49wzHխSrjXCaɲ y4)[Q>z"9 %Ƀ=uT\19-BiH-f!jg{]~zY\; A#̪><ԋ!G 6k6 c[9du-9*l+!њZ~dxٴzǂɑſ'/U竵+SH%79V:D!!dI5~}̵q/H.|l0ze.Jaw1v"\xg_  ƥz-bt5NLgaƷKhXǟt' )}5y)j (Aʩ  *VEJ7 `>~+_*zM{XVjEDy_!\ylXԥ}H%#_59a_@+~jүԺι_/+V[09XδwE7G?ߪׁy%ÏVd~u'X06qp!BJ>Fh) hpRE8Dl:`uCe^][px˺Q ,ŁE2S5.ƻyk}A*@iҏ!&!Zt F3Sm~NܹL%5DF3"# J)֓OU'ԫTuob-[V~#kO[E/cIB7aD;SłȌw^8Et]W6!eRB:nBqn6vS\33}A=&eӤyLj}# 6]݁1Z:ކDS'>MOF ^:Ag]''/xRd_:'%f,@$GBPppبȷIj^<.AP>mP.h4_أْ{t9 Cΰo}\e !l|r &Eb rI7 gG)!¼A#˚n/"m$>o|CXfuszbP=']Kl5QLE G7rfClqx2X "#OF _W&^L|(բe\r|gc$"Aֵ!âis|'|頛#= O`r\\xxq+8vF|;e*uPoP8rNòSGR6 #gMLFZ?j87|*UCJc.BI :dIsF-֝ E"G,/v2O:+Tᴱ69O!*Z.Ku[l!*qgTO~6ؼ,1䪔2hQ&u}M?Rvo`h*_ " a2>xX$xlqMtw0,Q-UIeA}1XHdٕg&Bp_ 'kߢ-0ӶSw_᜾CQjR5whe~UBvz=>pEuyb܊Zr#}@ 64S!'Aθsirj5oIjX>0:Yw:a3/XΝd/˩l8:5мQx}CE絏"LxwQCuW0D !‡2Sa GF#b8MX/g&@bꌬ$x:.VhvO\#<5ֵgų~FtnI1 k`ƭ/%rU4 jܯIB.!u\м/Y ~-iTi%qY[-odRHT:+ì8 St Ø )K1G ZNsT@=5,ĭY$N7|!{!aobcLPRHEƻRVM؆daI", 'H1cCquWTexGkCz>犜 qУQp?lKޗj< t0 F JQ ` CrAd* -=`:z4"(p{kDYAG6sES ηޗ*XfIdO8\(˜K~ꭥj =Fxz^4䏬,欇,ҟ|xP"c#Z5WC*q&Dn<(58܇E\n!aa5<ᣆ+PsWdYC =jiu9/qe8$hWj1YK'&I+?ޯoyLqz趨kU?ȓ*@hg4}sFVPek6 OXc2nrg.ѠcnMnfvM~ooFD$3aDqjuCd7i´9l\g}AħM9ҹnU$8,7Nլjf4=%ꞤatX0DFsGjZ~=NKvH̼:8}N8JkI*1mS aŸ *HPI v}MW:Q}0eSo~Y`?M =(U &U1wgGD=cWk)15=*C=jN͏a> ,!%@B!|j4Y edc-Z/}:^3tlM %m3k&m.΅ږlSSfbv*HG< !#E,( vh q5nW^['# hl􏚇mzaR#Udr;li'j{EegNU yml2D'D ĻʕpKW5YSdt&+ ؗ0"N;8|vrA]pm/LD z9(IE1ɑ9ɍ9ʃR[)L/SkG% 5>!ka6uS[^~b/IyDLUJ[:s']0b(E Qt1s *\_XtFG,!R0hje?ZZx)X b%Id XժQkF0ݘ+;}L"s|Xm\'}TWư+𹄴 eX\Nf $a`:!|Qr x>>vPaT8/4DW*o vYl&ׄ%΍A'sAވr mk"\bQZaҷE9XG!n!+҉R }O_M豴FW6>$CSs)u_` V_m:߬qh@yW UhRWO:'Q@Hz9#' #M23ӆ4{:nL{Ed2RJ2|s#{J2 |(~W}ճ@(y*5؄au 6zs3J G }Лi(\CTpPgx2{U/I$nݬV-0yHA=y^fstKٛ~Q(Ɯ S+-S[].Zuy`[8f i8T<.qvVeah"2tSYsK{Ѭ]A+)jI (~wF`%f'ƺ KmxI9iCMnb]Tx﹨<O*+ *1ۑ=:g*u|l>g皂>( [ lr֪Jo>h^)l5uEք^%[/9in PdjffVE;*ThL5 SޭsԄ`xP⳧| !UrTB<4F+++7;\K@4 JXgN +37w=,ym5W&{lK~0ɲhZm a:VGpb.3F`Ao ~ $aݤϹibXap46R pS >e0 5y6x0IWۤ0\HڏH?'ܫ5f-^ R&jDA E)1Fс6QcD2ȃeC _Kڌq.uET=8u͓{=bա C,H!t~9y+ߐT[Iڐo=uB^M" +Am$ؚI&:b!;dmsU@ge/? ̔cP-SxT& q{(Qsh@2Fs%;j/W_ʛ3ꨲ}H'lIPqX[}^)W烑կ_M ` ;ۂbϜHA~c;]Y/UҤ#EdRd2fendstream endobj 577 0 obj << /Filter /FlateDecode /Length 382 >> stream x]j0>Eâɪe{?b2n%߾1 G&yn찲M54M`fkգ'۲~J>nc'3u07g _ђ -䔽RReYNȚDZorgYq@e:rPHƼ2@1zqwPX%Hz*(@<ipIɣ _ ~%lyC~EF~'c,E__;I)/i ]8}F}sba,o<{Vx"endstream endobj 578 0 obj << /Filter /FlateDecode /Length1 9936 /Length 7258 >> stream xzy|TU{}ƚN*P*!H:!@E A "@0`>aFdjHcjAUW|Dii/N!ٹT%}M߫33ַuPBNjUgI3/@H*"$A= IsU,n[w̡sm\cM lE|ǯH'_}l).c4 س76ح79ֿ} (ze}!R9) @#r 9uT2ΩH#"#whŖ6Ӌs]f?Ӟ<(_Mm/T׎`l>V*7n_,$AV\|q!F"*ezIacmvמy˒k&w^HcaDS_td ~a.u| Ǟ{≝;x98nmg4: &ϝ;+cNY8"纱=.C,uo.ɔؾ1Au)/mD/OG ҕn{~8-{M݉zcq цC!#@4{r}ѽ{dS3ˌeeN/:eLeq (%iYòoˮή~,{kةOA$ v\W7}ݰgͯUqtëf<;az*-Ƥzot0=HacK7M&op$yO6bP i͊.DfO7 ;PDm2bດ1}6=4Ҩ~pk?ҹAV1sY1I3gW[ pkM{UXƏ"^H󴶆v|EY_.zb 4_le Xn7:]ݿop+ri/0Gm"i5 _0 C!b߯1IaP&}b;:mrd;uoŌ Ӟh|3ڀv6Xx]6 m|͹m4EEyS;Shǎ т.UbyV[7Z7nYzuQd=ԡi-YuEm\ݏmK'7LZmt^4%lV7lWk~f|<ɣ-N8cIԶ0ݶ3q 4WظP2kƚ\xo͸t0nbuV%MwUuDl/݁HIWEjZ֪jQvU=fwk܅8mOOl޺{ݻ!&|zc_oo6-{ c m6$H#Fs]1r ,K9ؔ 1kx hSt3찖֋m{ΛEfKKK ˲d+ XVZIRIrIJI$$$2kiRmrmJm6uicY[.d%]Io}*s*;V[5;OwtVOH7л=tv[xG'ɯ8|C"qxe667Xun1na@^"E‘;,[J~H6H1B6YUl_G),-! -x-:%ty7?$CӞ_肐k= I FH## ~_300</T ]]'^`םd}w4,~ƥyGDØێ~2"'ra(WX׭[F\ifbǖG/[8Ln¾h bc# qJd8GLxd*KtBR٥k{N{iD`Y~R=D=*9I&y~TJmQan.`jxڋqQLA%bϽƢCcvF<(¸Nw*k kRAn 0pU9⪪pvgG@7Tk%D6jpԉ0x&c%~Gze29Q^j_ӯg7bҧ eż ')Dc*I@P$,h;+_sx\)Pӵ =h\P6 Њa<'1KtT,+ŪZp\$uUnit^&)ejV -}|HYV Վj2V 1j+5[z&:M~EgIQ'/k{_Ǔs[AM¼CMtb2+&dQ3AW z icP'h\7<"3Վ_g_9Q==iG8܊[u~RIVM*&E86Nf%,ýeZKǓl4H1THg< /Y;o[~:`_{q; AANv"vۉG}_f䱍f-c&RYmt NsN.΢Y4O 1l Ⱦ'%=^/Bt/Btײ INofv Ii KUCÝ Z j3YJA&)A5 j;`4@-FHɒ%[Gl7ll9a+uVO4fr:͆l>[ܣM3nwq'"JK0WT(8jJXe9bZ$=mFݠZ -dζi%Rϻ^f륭17z/IwYTt2CYZp|RfQd70"Xy5"iZ5'a^S{#UU<05ʺ|iwM.XiX@.dl^c#G0񨑧xdr. {YU6dZv.mȵ䷘V2(6F6b!AQ(R {GZ&f2VeRV5Fԩ~Y!M ;g:3 `,kdvo J-,W9*8( PT1lQwTH+ʐÖ!y e4*`-$c$c#D'3"y)]!Ӎ菛Zą-Rs/tCلNlN1eUf^9da9ns= *l'nF,sI U:-:5 Tt Ksr̂2G,EUZ^lnxTP>T~ tA:N,8CM,M>vcMzb^IXY 6⳿?H.r!Յ[!wȶ_f-U]yAEܨYM h'XǓH2I~R1>I!RHB8.d݁g\ld>N:vQ8FS#JGwQ-BKqF)$N?\.ҥh&(#kg n/U&_Ket|FQiu1 K-&uR.>oP d6U}d? d )<^y $}c^CWINIt} XD94FkSRӀG 4F@d4FR0[299bx[G Ƕ >fl1<|oLYc`Ƭ ϊ+<3D+}ȉ>@RpHߵnu;9&Jzb"?}>yow_&"HFr/9s2+r d\K~Td}?+"aϾ7rT5MR&"WI>>gT@&|v͋pP<[!WH5+V1$PJ/\O&DJk)xlX 3Q@v 09D}џ8^@0'\/`,^+1~]Ir1QF6.Z֗_/5c0LWy>j_兡C|!N,H>>>Ph(428!w;r \x?ՠO>r彃^YA Bfn! ]@Rq^CJ;$! D _ qx' bS18 LY %.#;8nG4thTM@. /J?`+2@C|jÏ6KON?endstream endobj 579 0 obj << /Filter /FlateDecode /Length 2950 >> stream xڥYs]51=fNƭIy(eER@bw_d:O^|Fe&UZT"+dԞ~:ݛ2U*8`>v_;zy _/Δtfm|ïә.fy:3FO_O2ly3]p-hZJJm |n$@Oʁ\;^/ w/ W,aLJS$Ͻ"t)ؐLbmKWiw#j83WD,ӆrZ2.9Cmgy&[YސbotR5ς"7wqMZX,5$"{}My}Q\ A,-{Cr-mGs ~tLOay Nz{[?|~ѳ1,:d?<ر2?߯<ĭ'(#۟:7ňOxGttZSئf)Rgcx} E>t yШt"m?9IJ(~c1Q_rS{wbHE|$|iջH|q70 +qܹ1hǿZDh(zKYR@tLQ~!azoӁ~ .9 玳e6@=Nt#*x0 z(A♘<ُ`8o9&Jޢ%یii@ w~f}TDUFHMtm7+~Ǥ(O3W7<1e_n@ml͖;q563Pmve2wG7ԭ@Q4bepM3SA0^bHe-O(."{#>Bސ]?Czh\򓤰pevz=AӐ>uPB/n4ԉvGLfy:nәoNK$|Zωs~H/Cm4b *GT4_H&K*AW>#&WgcIi=;/QY8 (H #G2Qe`wlc e0.t5WP=AE-:IdeeBT}J)5AW,!',yNI"-yOX@]Nj^Tkj58Wdž3-72O\;d{4Dǻ] nLkTC++$jg74$4 쓂[G<KA/,lFQЈ|W˩*auK\EV%is׉Vް{!%G^7L9:Gsn98ц9!l}3X(st" џ#ɢȊ~]g'˅H3.Gk\I:EgBW u}q/$ǃ^%a'Xa/.,C Άb=W$G.GO$P^)%Zrj4$&oN38}rCC:l,̒*T ,eߵtvWN%b\=/ 8LC*ѥ E5ΣY N%W ,u؃x( .oe^>.ˀBVix2J`gpO [sF_?C*U&i꙰# URRa;^EwHwMCR,ܔ 7[}[^UJWT O\!Z jk?"uMuIH\o2'OJ$j$.-#p)H(q2HzcMt]ܑW\wfUc+|J6RY-x.]ܣ2O@~!!C`ւd͏AS2 dF)K1PVg0{ K{>R܀.]YTRh|ǬȆ)PϫH}Q–Kǝk1BI^=yEjcPfbYIHKt %(4UQZ:C] QwCbZ =K*&m+_ I)2.صQm').L,֡u-dpw{F6RQ 0mjE8|bC4O l$]|w-Dx5Cg,Ԭ|g] 謝,H(@kr<v #( TcqVO kh"<* endstream endobj 580 0 obj << /Filter /FlateDecode /Length 3149 >> stream xڽZYs~ׯ`V-a`fpzxf"!+yXѿO3 NUEcMlˋbgi5z.TE6\.&W*-# s sdf.K9u;-ʤ]vEՁ #7!}K/ʐdc7Ж%N+bȮ@UUIGZ)ީxHWWI^$q -?HXs$GP~F vUhR<8,Yq~Pp"/lڸ zdzgjEockYz"aʤ0ϾL/AȒ+ _.?+)+!ZsN+ѩDg+!?rWPsG8ISZ+~!Ɋ+oKԯgk}4ifܪ_@A~ucG؝yw+>8tUO"_Ե7jME52C3) kup ΙFCL5Mt2?2h>ȥ9"܎gyy+*P? {Yn$IEo>V0^ bHsԁ"]f~D0l{ \gE'DlՆ%Ā"dq݇EH =^\fFܲ_NR*#@zKЧ7{ {->}6[T `$*YؤE摟-~ȉ58ѢLܾ#^o{7138y\ YճE`,XN{͟[>Ʈœ|HGIcS@aR!TpM C錙(ՐLV27¬&vj_A g' a@70;(IW\qjUZu:wc4i`Fs ayi̢|9\Ccቬw,+kuދcxdD 2`kw<|2_lRcY]c);zJҩvdչzT<<{/0gǙeR|]onlϠ卂Zq!s&0"1XUdy.KJy߫+"fîoCB>> .##ƞc!Cp.[1Y3 ֯CG-='Cg+0AGBta d^A[ x6P[}rq <198=Vmꡣh{h\ |`g - >ny'࠶#kҢP/?}n?bz#$;֗㙌coZQP2}އ6Y(yy,嘶lFYl{f'y LZdfG0~IXc@V >[&4.W\18A~ _z.U:O:E cR[xG0*قͼ{}DwSi!lΙ< zAt)iN?. wP!t\`s[A{*"~<{VҮٟTP{*|k} `rfG0gcg(4'~ZCX.b y؅PU\'sHn*) _B޲TwǬG#k\ܹЪ9qz`Ò3g*:^VguF~;dvga*WhY̺JYOTĀ"IS,\Vٳju 1S0-Nq=$yD!9 UOO/r"7$/]d),8M=Q0KF7:3)6u NQF\M)KGݚMLNWit\SmphzJ)|pRTa%e.ˀ'Jr7~{t{ڻժID*f]1lJdn;\2r;'eM',P=-2n$: :uTB-& x\ <_֡ u^9QAŶ#i7ܺ(6/!G=[OY)zܫ^M$±1q-I1&"ZHL%kszJ^XQ;&ZF^kl(3XWD˿^,¹(u^^DeiW +1ؼ5N>RP7:~u9HŎPJg̙sflA+f710Gmųby*$REqxH 5rB0Ee-7Y>S *y_j0حpHjZ t8z~ %f J~琷MI׬jdq6aBq+1{5:fpFBI%((+(Ki* f{ qyۙz" ⡊aq8*!Zf W+\(Md&ypYMl>q ѕ%R3+Ew'30pendstream endobj 581 0 obj << /Filter /FlateDecode /Length 2044 >> stream xn7r %܇QHA㞒H+U+Gu_ڱӠ%Ù8O.&ףӣg/\4y#'ZN*S0}VN?eHRKQ48l;;紮LPFeәEvk;T(Tvb?䲰/+ ̖JʥUe}R뉔1F FeIkPڠ t[l۵uHd{ /hM7 /<̔}+"bu5i4bՁ+P̀8ȏ8iȘmSnphlTF v%r)XeWX,!jw"}fQB>焍qb̀ '3Y޾1uO՞!k ժ}xyuxlțY~Ό*#ڳU q2mx 9]A`gcҍnFE05lxC2tFTܻuxvt(cAsxx7fjVZȦiˠKVܲEoyl1}D1u جQ`ެmѠU`ݲ,w/^Yem fGnY]>h W%$rm#f5|MGc6JLй1ĂoؓѾ74.rOM+?A*I;阍ղLY#YUw#@pKS='nlNlnIx=Cld &q# )۞@co68=lAeK9BeZl 0D66/ʫDR8Y/0 d\`ALL0?I=fmE[yr0p'{'(VG/4x$Z`4>Y+eRrR:.@lgIkG4ֹ+7.m |h4eֺڞW=6}Vn?9'Cْ $R-:$D2Ԥ1+ [`hC`N`tXvoѕn L9K:N=j^/Uo) Q8`/..:Ԋ_0 ͥ ; :|wQIwސyEAI-*/]FBnoh $1P ̸BkX.Dn|0 8{&[&rx鍉U-^=V*Ó{("IP(t:nTP/n:R3 ZقGꞃ lXZU3ª6O[i8YioJo/$.E^Y{W "kJi:p]acZJh\*EٌE`$@q{ʍUI*zAnus)Yn\OLU.:-z7n+E]UUN5NCڥ.=}F}:qwY'*[t?swvўLhܪURbq;5WaiEUc)Z1+ )L-PO Hey5KCl]4j=@ 4+'&WNZ鶏tT' JHnN6mw2q /^H]&oP py80K'ᎧnXhYqO .W=9I[#'|oB2S^LTޟ,fnAU}%t ҽ+ck{ŭ0\E}jiBEjFѿײendstream endobj 582 0 obj << /Filter /FlateDecode /Length 3785 >> stream xڥZ[o~ш\xk_lv&:O%֮$*{3$E6p.g;g&O?]MLTie&7wSjRdERlr2LW9goyk~%w~]qk[Ll>_ے?]8 ig0K!lF1ӿgӓH;W\R\dH&}ZT+BèlRVDǑE58Ar8u^V7GEd5m%Zۘ[GiE}+~=%mOcTXjµ RZAUL[dAoOi%eZQ@x.jO>#K6"Ywu0_~5lvAw<%)%'uml~'$<1%lLBvIgYNFK\h%??`)~q}A!"[P|LHS$f&ZU~j(>f#r94ߢVę`\hT5),"#r6YؒyfaE/DA1M\aao'D洞iW-y5-H( nE6[˲ig&/k˾ RryVSF9c-R4@|槟hfo ][/;f;N~ԉ Dcw <>1_dc$/,B1'\&qz}tY#>MMfp-fo9ɱ^gJt:m+TŤh@(Ę^)4;L2>;&HXJ,pS=E,57zvaEq0y+-3 VU\Y MoQ)]ުVu}">]̎"Q2 'DaOAjdzdr1ݥm"ӤL)lPLGq>\-" 6[X$q")6o?DuhAEY/9|.x/ւ2[s'ZmYм׈Lwk<8Rݝy{H;w|+$30ԴJK>J3f{;B(sL/(?[I_MOYWEʪ %U&iT>)hafs͍(ƢG ųďAh$Z7U@*iRhXN1؊-kn#I ͹u%޵8s.tX (XImR" G}d6i$j/["FT6*5bL zE ѱU5w4K/3}LE::4`wX!{h<==MbSczaH% ;W9k(pC U7#l^Q<W5H1oPbQ5(!='R2<HP1#ȇFƙ.c<V0B]6D&J>Hupiԥ mP]vU UwA=>hҚGVXʏA9ilQ{3ݩKYn~ǐnxRKkT܀^,=U; lAy -' I\s/bV eԾ7oCw14ږ!c 9|"=ϛVZQo|n˵=;婢J8q a=X84Lĕ+k"E U+0,|P-tW3.,Yw`֚fsGAI!5KCGwԂl鞨tv'ǿ2|0uw,-ϫ^TbgMn. SBq!%L%7~PS]x#;XlՅ&VJrA޿s& ݓ*|W$v ܕCCj uZA4R2n$L[#U$܎F}edYqϖ{XvZ5#07Jx?,4 5C`͡{iDo0WŅl:LRe*_t.&x;=M ϺBƚ$-G]1&ӽR2ZNH HeFU$} l73H ZHRӚ>c`N*9:L+&ĩxxqnVK]':fm6Ÿ|ɗک^L!Ds Rm/9ޮs)uf vpRƓ vrMJ@%ߥ, \ve(fIi 1o~5,{&*'k31'wd@>X^H ctҳ2rnKʴcei ]J4ս-]0vŝjڈTK~[w~6g*1!˻\\0t+GXQ5XgQ nz8_s#7;'w"r/%t OZ BB2]Y Ϧ" @Hs\5-}O{&=k<$5iŅ v:߈R6vWnQո{b|*_,v7$P%=uO\wGhIvQ.E_$Pendstream endobj 583 0 obj << /Filter /FlateDecode /Length 2293 >> stream xYo8P 6.٢&9pEh?䂖d˰>Q3˥Da׃!f)B?8?{ZU*/Z1Uq>/ޗ_2i`D-w2s͝Rq'SkMfӷ{7j_ζ]2\My &KȒJ$pΙd^/gHpTVT76l},0c!ź#jVŻeY|Ym7F;hWQʿ"sر ϳ)lFg}G4 (w5p'7kZG{R>Z9gMVK{Vb-25 D'r-"%kT&p`]ܱ֔RX[[=q<]{#ފ~5Ϡѐ MȖs2![ՁIm" h֜]'Pg߇zHqlc}ᨻ E5h. [F yb4Ӫ&dP&J;:NlvGL+zCpK lx`0mGVa=_H SP׉HnD,Ïs0iW͍E3KyAsEN@Ƃ>ZS]JTɴ!mUyL_/@| ~oxَee{ @5B{OiK^KEr襄ͣD:xKj#1pڍDY@k6ip1@[#}34_&)OFZE1WOkBБ\ѧzv JH7DGTCnNv~ Pl@U#9(MS$y7Pj0,x dAhﺮ!;bb]߻Uш%^nhHMbx,Jj0 "ܑ{4`i*0b~4 v8jz]Xaj/7}BO-o_CG1im/Wr:{p p&0-ôT/?Q"} KNPCe=71QJt'Rd^yb*$-aoRAhO)Ⱦ5ϿyBMfYp9h똱I|nK^wmA U[Nc }Ui+oOs]n})|F FNUO=9 x$V'){]`^F O|V Fh/;h\!p7;{FX @ $.|Q9N; *2a-!^y pdM|3"^Vk0a j D{:#ٴ(endstream endobj 584 0 obj << /Filter /FlateDecode /Length 1386 >> stream xXo6B *Z$E=u$2l˵ $;EqȺtGx N"@A*ԓI(tzE7x_zG}ٛ(/֪w ϓ \\F09\V<ֲqލŜE_%v}@!80 v^lYu,"#19E=fyR~JF$Qd'/חl9'P?㨗-GNj\ίVE˔*VpFcJ `ɤn1 1ÈarCEN 1yM_7.HG9|IZ|VH+v^6")Ś qٗW< #Q2dyI&V*j^hF_FÃ&@;VR3ޮ;*RT_&JİU5bk ?_MjT21Ԙ` ϗT;\tQKۨf_r[22{XaËaREβY+]KCɩ׮1;(PǞ~;Q_?\8=cNyjj Yw[F.oy}9w7K[yM,Lek x* 'EGg@2?JqKyާIɜnTɀ][Ɓ޶V[nf@Bop E΀.c›96@Hٜ"Ik;{R :QQ}&TL>|bAKeD%ݫbF;%uM9N563/psg8ۢϟP6ոNz׸ٻ*]Wuӻʀ+-U3P4_R2m#1n5ʻK=#sCrJ)`E 5;}B-YN}8m XބGb Ν.9]V2`;~çMvBjƃO'Fġiixx/endstream endobj 585 0 obj << /Filter /FlateDecode /Length 2662 >> stream xZY~_n+**7"W\hE{ke֨0|sqS-e<=n"eѫHMJk pXe6g&.YdZςp|`IXIlV2P7b#eUo?ʰ9Kx#hgU9ܓXW=9|4Sƀ$uCXjDž{Zb~Q-a=#|zsY _Q"GfѺPD3x*qfpi@\R0)"=Z iom{٨)926o D+k}"-Lc7~W}\W"?@Ed a)PMGײ YJmf. {JMD¤ſ [e[9`=}C(?tq D?h^(TroA~]/:72=0%I?8sԩ{LA3gPc%mk 7B}\*Uf%zD跩O/hvRŃ<ދUM(Oh d~;op}?*vF$B?DUaD9cO+ pZ;LJEvty҂|ު|OT\| tՀ3Yv^-(D33U۪ĉnJ!5݈SI"g5[^0wz%=c,W+)|%#@O (;!MwqE4oKٯ$+1[=1@$g*)l_zQG8A+F']4FPn]l[헨dT~d0d>*EtMԘJ2'g~&7Gok]_1%}> 0{?Grw}*zrTP-`%8}2,4RÆ! 04͗v#f -y4gm#s? OGZsʺԴX UC?~j/JedO竺=Lh' m2VCrWB$.H,u: =hu-LP*ڊqxK'S\aG $mYu#ؿ~Vz-v(88GGz'fC+T@"$5DD@XNwkߓ"^n(5Y ͔mKd`%pY6B(I +Ф,QRN^NC t8"%UfJd@o>[ؙ:ϼMAC#@}:y9 ^퉄EaO; D} O1xу&D.R~I[F` )bCI Ҥ 5?<̵2Ov Tף*iӲGY{\fNN ]wp89;flQqN"6,Xrߌ]|o 0sAGPn'cF9xܩĞ_iK{Z"EƴG-ar{f||-tm TT`V$RLH5}ǔה `_Wm1cV.ˈFߢgp.q'$:[IƄRbCsJMb63ĉigcCg K|+;AaOvPZAǁB"%CuBa33Due㼛=7naK:{㢻g^j G_\4wҞ4{BoJ8倸~|SèlL[;Ti7V ٨xU+ M QR @P;CA,ooB<4QyJ%ErS ?+&{g]TPݤJ m c̚HyLeruAX09 ꐁ|OY]/0 ۔Sd'6 o mqEX0<[[KCp4;TAvd%_Of|KŠ|^ P])[fE %I۽ÜNjԗӅ]w-k.e]YGq}*-endstream endobj 586 0 obj << /Filter /FlateDecode /Length 2485 >> stream xڭYmA )RU4r]yA헻m+mm$;Կy#fP,(r8y!Z|sY*.Tv66Xi&]n/uT~ZIwpOu5\ ~rQ럹wWL[ͧeYdoQi+'Csn_#͍,հ0Yktd[+kbee $mJp'{ѵ\, +nfuίDY^9DPݎb#l|@f$Bν܊o;QelUݏY͸[k'_•lBHDflB8TOԱCIn4OK#O+'>ѱ*$jZn؟&+0NGornDEeغ 3X>FZ:@G_yXJT'-(l 0`b1ѳ+7`SyUrXf$w&b$R58G8M -ň;b#?\dD.6q* 76>Zf h$#yQiCh [ Q#kБCZʎ壈.3Md8͇=b19xfұ)YjZ{`T? Å&D^ghQAzs'hYh[քm_! aU泤2~  ݓY!7pZi{u1yB̏ |<ŕlc=ن@Z٘hh5h;N~'`p6XP^cFx3JKhD_~lWoωDÝLu~L 8ۆ8܊ Ξ!4-'W^AZ*JX)7]RrmsvaBRJkBpگEO7 XS$w#)5'~ņl UitqXMCs/ۡla^Vnq6 q.|ߦ6x&I!;fGũsC>{vKVsiWt̄R>HIuX˄ <Ti\5{ 7@TMIO::ثb_pv/7_0u`hG9zE5'TyJkT&N= r|A>OF}kߒmYj6T 3J,T'1 "9qw`(e>LOdf7EU\R~嗘)ۛQendstream endobj 587 0 obj << /Filter /FlateDecode /Length 3605 >> stream xڥZYo#7~У ` 2I`6`fE[jᨥ~E6nYNXlb_Yg쇫ooyL)=zVJ5nVsm7o"]j`˵=| OwvF:[0,Ն nUNw4 9\[q(6m[JIptbPs,r<]2gNa}+fnmq{ppMnPƒutB~pL(cw$O{4p20Ci;yS<9DeӔA!LYR*I)+S?=EgA\-IMrI{9xp'&w-mcp,R-C<-Ơ0^&ôG^"SZ3o}m@7+JDQw(,ٔѬ>x,hƲl> XV,/}t+27-SԇP!bT,Ff$ӘFХh}myO؉8+uK3ud+l'vإUDvAcȬU!{UB~J hzɆq-?tD(0//_;QPO ?,| WE]uB'%/a^"P)a.RqOetv99r*L F5 @9(V?^TQG}!͇g3[Oy4.`0Ҕsgx#dvabCWӁ0)* ]gY?Gq eO5% ;^MaQm**W֩]?&8 {mIp2ڷ)fҬiԲ V,aSꑜ[$S*R?ܑ-gAQ&h;;H>3= w,7<)K;]eX˧ v&d$U?g .WzÉX{M4.@ xJWf㈱{dhڨ'\^n0ŝXBܞ(h-RUMV&E^:0z8 *e'YG'@q HcQKCȠ#׻0zpa淁q&ɡGDir=mJ-GaSOͅ, (6Е{FB1mfC0A4Fa-IURiItƨϦ\b!hhH .7dpnpc}9(B0Ij$DDL&IruC;eIbH2kjzFۘK%K/P6l/%|PyJVaL:nIc$$"<דd >bm%q/#P]`D($XA1⑇9 Q#)p0mX? i5sAL^npFTSI|Atc,'#BLb`GGUe ֕NiK^bpE1>&mÔP|3MaeG%oS1 [8Rن0.?%%݉ZpZa x=5T4 P=Ea!VUq2eX{g:`6$꧲ɁU"&$\47Iw+N4TnFU~ U]Sý,NVeyLv$m8#GT)RFx]or;?^6rI*piC)_z=KNPʳq0 Rf \ qJsTۑ9"%=F)(Op[;`8-xnk{Mi`9r=> stream x31ӳP0P0T06P0P05WH1* ̡2ɹ\N\ \@a.}O_T.}gC.}hCX.OȠl\=%endstream endobj 589 0 obj << /Filter /FlateDecode /Length 155 >> stream x313R0P0U0S01CB.cI$r9yr\`W4K)YKE!P E ?0? J!DH" @ l%r38 H.WO@.Eendstream endobj 590 0 obj << /Filter /FlateDecode /Length1 2238 /Length2 16150 /Length3 0 /Length 17469 >> stream xڌpj VcgŶmvV'm llfc7nlʺn_7ENJ/lfosgf`ʋh1XX,mÑk,xa!4v;d\l̬ffN&&  ybƮfy \G|PR9v-M@ۏ6U{SKpvvadtssc0ubw,@Mpt@3_ ƶSc#YX:Kjof|l,MvN..vf@GGv@h/c3@v;:yX}[r tc; m?]-mM> . ! 0`o~NN N6qd+GDmmvNp'f4㿇kmgfdnigf 3Fu;/.@i|>LLLԂj?8x9;?h},́༜]gG?fgK;??@;Zt>֏lG̨!!&NoUػY,ffVn';([?vѧP7T]o" T2Zxcs]?@&_+bocu lmtt)Y:Zk]%Wl,JN=-zf&.Sc'V?Sۙڛue,cGGc8Ubagx1-02;>(;Q/ѿQ0A\F?(_ `XR+Qb0A|G".&AȠ}dP>qd0>AL?t6c/h* >6?_~@Ko&?Z)@X|bfY~t]ъ??\>p?B>4+GNaqg# f.]?cVHn݁p?Myj&4Ө齖;\Sn: S zC&)={&-McN ӫ {~o!…/^7P:sOyCl>F=Z/x<$kʙyn5{H&w kKzS76- a ֢WIQLhT9&d/l5]|ecScGeȻ3q;"#G6ٝب9uų̆pNʝQOXmo:S9p}g)XLru{O;8.}$`ިi M2[gB~D}+ٔDzS~b$b(Em%xɬL8a#c1&IʢW|2%b*8^.h\YUbl\G^g~t6ȬJ,{Fl,D-\TL9fR~wu &b<_o`Gl*r!;AM:V=wy# ionUp/dw5D 4fs:zY?!A ^8ʇ*5ݗwzzl24gB;x3_ZŢ4v!pvXlr9Gi>ʠ{}ɤ:*!kݮTV2t  S2|WeT|:|K첫us/$;r@˓"yGL@1EKs95^!hd#6|$6Ų ֳ U KO>;Eay5CtX  >qYэ L5JOǼ&TkX+N h rIp$ZDlW Z4 5w] SʧZ>'0[Z7}ʶfs{l9YCL*2}^sE6ա ,1WI3FB9cq&'[Adl4+X>koCS(6a;M㌽;!.btl3iKSV,+y ?mUtNn.lEs (WHU@.4A%pyaheO!q? IVUK *MnL;5=6rq2ı&̀Ώ %Px(R[LFI8G+^B#w+xՠG|C47nO -26v4 -LjqBM(zKZح/64x< #w)rCK:߇D}lno#Qҙ &xЇ:|br'i/Y5)16?O$+w9Ay@=nDO>wbt^XCBVmVA0Cg#Aț$fa'j)ؠ\h>Eが`\W< -SQ-Pr!" h~E%!( z=U:X7zZ:Bٖ4~J,&XxD3LG d~XYEEXj|mT\iiކnxQVbu}INIn7Ȋ -$ 3h5ZOn(lnЂKٔ'sY Dpf&IxosAڛ f $Uǂ]_?O4,/1e&,~K;r=hTA|",%58܌@lkC]P1xgFMԀ%.~brfeY/e Mv36{\Nr e0=YH)Q$λK6IHIkl(['t=KnI\y2`g @0__E_|pˎrAPfm)JU+u:=HLRBnSovٳT), AMJu%d?ZP3B!JZL\bX>d<erx8g qGY3P+|#Y1ݑS$s$sQoNWӭ4A0 XX%8o<<)DI77e,jUҧP 2c%7ήt@,n6'e}f3CZ|Lژ2^kSO4s@Fg KNBl_'HЊE*"@~*y@I NJ6̙ Sf%{yP rz86OM yZ[٦!s:5FV*TYda/iUr`kRb_|R%:?5w4=@=4}]J2㗄1xlQY;Xy( o81aN*|gʘ@pmm+$goW2wZ\'}NYHOk'Ҡ|F-gg'P>d.n(U_=@$ӂ7Y[}i6DD<3 G@!پԘh37j\<K0y0g4/N:YIoxЧ4-ঌ,bd[;ѢNE> 68e~T:$3v.w|k!`yR]E'ﳴZ2̚-f=lab&y{o"gyg/a8nj}9@dg予@͒qNeoM.38rwH(!Vk$6ȭkoDv AQ=*F|utYJeeҸ ?RYf:djEh́$(>'W޶S|k"Q5Vgd 1 Ì Q tۮ&h*#+hMP-8X`@Q"}L4 KG/Gۭ" D\ Q.I;:ȧW[/ "`lS!F Ccfm~&?Ns./G1]Lːw=|B6=6α&X]8ox+ "[h{3ZQeB׫^="Ԕ/MD:cT()Ek֩B*KXY?Rl 'M&/j3E ٍ38a@qյ(,&9;5'Yj VA<%N_ 9?^_=; UI>pH i7ƶh|; jf(qBYڗ$JΧ耿(cn(CMbEyeRWDY#.3EJj S}V2eK- qg= 9֧:_Sk8|B]6ԕ2}<>F q@wFZ(jf #&j~W DrAe ɼCȟSK7%  UMFYVW ~'qB^^I.1!}RB9w'J53IBsrŵ5C=߲y=}x_{yR rM _N#9d Esrl2w/?dq.bhU=;\ܻ#wE>N],9/ژ{ڎ饲)״#YaQ`oE[hnrgۆy}t:|+o&MGˎ|dzY˭~1q-9V]ƮC&Ө$Ge3th-6HYZ3ΙzGL6;ITeTaBEH_rxC}ᄘŞL-gb!ok?g *߇qU zfD$*Qy?j@Cضx\^_!dyc<&>}[Sc|lNu,0G ?V o$pޞ}b/:d ų8b'7:`kQDdZ9Qz؉4u*~!.~ڧq>j߉ eGmOf!ڱ/wj{/~™8.@5c0 8lTX=٫MS,ouU uQJpYpg6%E@ism:Dr;e )gq&%¼ƶ^QM/ 0Κ}}"anZX4 %KVqwVNzl3;ϐ%Ꮋ}VT%S 2ZR ]R1$ nc7c?Y15RL[7osq6j09y8_ w'4Oqm5LS٢Je=U;$xF@#:PW+p){ *E(#vrbH0Qd.<`ֵX0g8T{*[HOؗNmG P;_qbFKҨ椸q%7dҤi!ѽa}9x2|RRu~GA[y% ȥ; $Ԟ\0C ߁ R-|ǝADxGfHS1S~<hF$r"EAB@M>7IL$ۤ89g.pW2T-AJ.&Ѿݠt1yVt = Rr7YA0߲K6OޭWqY_aO9/J:}~,ݪxh#ԃO~lU| C4#(Z Ug/Vdh]2K}m3|MM"ݬAGD:`X!]j\ɼ*&_)Pm:.R+ *ˆH[9g7d'+I ŋGrV6wGugSrB|=`(luo' P: fa}G\FJmsȋ+!ؽec!l:9cIsu,k ,TnC} {M4 cSiE.~.^c9A\^_3aZc;}83odSД4љLQPK4pغQ٢$QW9l@Af𪢄ft@ g RT1Om %$Zs ɃJ~" آ KOmJxV=WLOJQo[wL <#"1h33zugpbPt(6G$4'~>斜tK"`X#/R$&@.zo;U[{`|,ҽ{deJK P1&k;ˎzƿuIy~zpc_*8JՒXts;:.B60ȑt`?WH͓TmQG9mR-eZ Cu/ 8SSĈA˹i!a~PQٻe1wҎ7=ʣ۪ǐHEa}r7LvFؽx߳7\jeBObpThM#;)tD XHr*0茡]w.f;E/]r!&[2V~%: ;tEE\>-iHtE=3!? CˌgnsO4Um>MQpk˘..(LGg=m44uWfqtAkn߭LG hҏ0SQ&^ IصGн[oawba+ 4" B$tu?FJu)CxٚWjէIm&VwhxٳO)oQ  ^>W?9kM:=~ (T렬\M,s}pPv1tWOD6XRo`nXQǍp:k!7Zy6yj?JUlc'bD[uw;+z/- 06Fx$rc'Qj+ `WO/gWhp[3تľ2c"Ը0<$8W+%57ͽ|^h'|M?@_\~by*#LIf,鯷5>4 whF\{ž~*(Q*&RdaY&*0#!.5ҖߝR.?|#u6aj#l췞3&%(=$@8ьQ)g>5]2m7ۖF);`y 3n<zDŽs6{|s$(lb.`F5TM`oJ %˩Z/&݄ˑGsjk2ag&Xqq535V~%0=: >͕Z~-߫dEelevB3-dttlK9mA mNv됤HhCHY> Id (]Ie1 r~7X.A~0FĊ+0hUI{%&ɾуӶ_ĸ2ʼnJ{AĽe'k9 QIOxyO \V 5.( MޗcWYNp̀C6CwXK7A|Up`Y/  Eza@4}I8 c`3Bu>m}xC6hӧAGCD3H3tOKGy\EBBJztgt#~Ol^hx5hLk$? BssS&% ފ3]%#b.R/2p!~ym"dta^*wyQ TX72t+Oc S[b[VX t֫k)ըnɅgױJ\$_c+ io?k= UkXFOWhބ{l\ic2/9VT5`f;5s S9ծP˞řQF1u_ %܃Me'tT%Ij0- Ħfaɬ3KaN0 ,=} /w;`t'Ow|!ח=R%0 j :XՇ8>+E;^toL|.hl2aY>_IzۉI]fCh_&_T$p{9f1R|FOd\>lYBDXQP{n%]l*;.J^f;|V?pߕ1I?W#1 #&_X/ŪzeH" O2ڶ4DU2*..gX:UT-kCD]Oz"jP6~i1eTδ]eZh1^[xgs,Fc:Y#6=A} ET95š,:qet*Hʴae++;C֚z"x良ֿӮ$B JȘ2̞A?n%;/Oro-jP"gJbakx?x8EmiԾe—BEB@Is  9tK Ǡ_w xdԉ;2VGX8)SY'&8o”>T9#CG{RA7od&P~{Fj-Jw5-J>_ r8LH9O޲w#/EɨD}HE?&'$f2s˹DZ E'o0 H܍OG`Q9t3Γ>ʰZߴO%a.s -/(!#yEA&h:8E+!ŖoA3,xcͭ8+(>5Q6&H2+e@?qevΞ}E$Ʊd+gRNΖڶZv#߇r?VG%&XJ-\2a,; !=f II& X܍ôEX z*ygGSoyVUBYƏ潊#4_֑7v@߭}'eXi|J tqY&“=UE3HR , Ԇl )gO2;췲@EPGƷEb`e\ZρwJ~+[mxa-j>Qߴ]anAfj-:ZkC~Dxԛ0ǓaZCqB-r$SwxkdgG,,9еf}>~]ݷ}Wct4ot +w̪ov/;Yi#ߟb_`"ݿ:Of2P(>Tv$-X*5Ex6j2M$۩Q} J1 jwp|9RPyc~*"(F| zoKX*q 2i4zoDI-/'6'1 hz!_]dx.xOtz۪=VR0,6uYl C`3ݾDRhHpB 2Q_UVtSVaz41ƣz~*ɳO뺼E\m|i 2жy:Bئ&_A-KJ:b[5OEF-v"X`oyb}%4 U~ͰyL vjXWb$ysA͘QwIHfJFד k "l/nB@JΏNF \, rDKpC}* .Ow83lIN=M^%=ۭ$>֕ݜm.PXBCb /r.tn6P"H[~nmg]JW{g'C'xK~RgS$[CwЭ;=VBυj3A䫪.*L+D2 1{7K&{Axܭwnb[t\a|,{JwI4ŐOzQV <$Vp :qm4]>vsCQ\Laj$3bg{kDJ 5eK-,.D,[pysS$1a(>7Y?Ղ 2nu qؕ]&YҷJOL׻+ g l'-OZ6?G&tZ;آA t:?6})y0J5 qMF^W|ݐvk<,/md-T2q%`wme3<HBQ6lC075641v̦a McZLӞUV [` ٚV@Rq2)r[)'eV]*i0 -H̿6Vֺ*k-+ЧDԺ[1`1tB8fuvc!xPg:i4CYb۫XE3.LÍv5ԥQh-]۪*vL_K]Kvh}PD:7#{cxHAz`"pq\[20&Ro0"|Gg;7(Eb)>WV)N2+dE7ڲ#A8/H#R?8\e1;F/%쀝͠=(5mpoaa # پȞ S ^PFp?'s6; Ctʁdt}c?6KmJފ0x̊CE d#|)avQV~zF5aR]6zI(>dFZK  W98palG&n:BmZSODpf2ʉ glOp5E<`U *c F؍d нp}tۍni %)endstream endobj 591 0 obj << /Filter /FlateDecode /Length1 1443 /Length2 6782 /Length3 0 /Length 7765 >> stream xڍwTj." C7-ݝR  Hw# ;?߽kݻf}v;fzm=n[5XEpxb9 ]!03CN?(!A\B0y+JM;@HX QV[@0\{l60os34`gԋ6VN=  6 EӓٍbxB]Ji 3@փ!<` p؀n(w-@ SQh(p* _ֿAll`.VP/`qyH jK 8YY~nPX+;78q!/7"+@m``(W|8Uu/mu<>vݯl]x Ww_(@aQF8r-Q\v~;0 @~>[ `{(l<Q>QܲAQ\^eEy5%5 -!>|@7 Q{Ѷ[ 'XT_gk0 C1 `f@A M&7v ǣ[KH!N^Q|uGCMUUl qwo 52P{qS  ~  ֆA~-7/jlQK "0jhfkVpŨ C[07Nϭڄ ٭U9kW3#@N[lgoGOYبx1Tךp2Uא*Gn\Z [-'jwSd(mNԎro+H!ĕp%6ĝź }z-ڒ3qqh7ϱ/q<^T"hnƈ$BWJ`s -.Iw]*9ț hjrVX17DZ饔qu|I#razOO[wM 9ۜax;=1r+|#+wכ)G8 ҶNmMOP;R9+Qt]ҷ`´u|P6零7tZ,z>lKWEeф0*l{]}] 1-U?5dgj ֐ϣ#@BLkq6mEc 92y=/ɛp{(NIԬ-ۈeo㔹¿Z [lZHg_ܯ-Iegd&G{nHHNf?x[WznM.e;R-: 9L~ߤx6UH t A C"MA*L-yxl q3K#` :E9q> S/vVF/;*7{<"Ac6%&!{ྚ ՜9ݧ ɯK:/ wAeKc3&K &bȺr1fs!ŵq&R];ȸPǜ}|1V&8N"I'6kteTۤ&da7D07ϒ- zdZ{H!bz[,тҢn2_3B%fY&5*;PD|]LU \vq&m0_qס!g:ɳBWC/GAI-~0yjdlSn1/qC$b޳23'`GOXpl^I+}[ȅs܁F>eC oHOadߝE"*k<-:?uR%H?4.m{BPԻWM71,4]inz[ ""4<ܔJ3ZyAB^As|VݑG݋8|( vww J̢DgL53mFŕi;>jk"z0*)8Li]®1( ]YzU=Cƥ,^֞z\+--> 砞7þ[HcS+F->T}8MUJ̭7'}0Y}>ݍ?d=]q(> q{#g$xhb<+pgݟkve{[d`(6Kf\ٸ$cZxjSթR<)sEIMƆG?M`kwP0ǕTR}/uc=n<=_W]_i:o )78V3DTl̎3v2§SOW.IE3O}MuQez~}."B_=Z wKhF$צ;k6Wظ<27TyVnǠ[A톏j쒁3m~+{ ZDD& $f;.p zpmPDo9W#os1wvk7ީ9)V0!1(`[)W6AП^ao@.fAꕊB[R gmFXYrIoq-YO3ew_Uc=ܕZ\@XN5n$)pd -۔&CQd(:e.!jHmO̾iz#geGin[܀CZ?Xeי0=:\Ǚ1H%)K ^dEߊ}^ktXؽ!VHv`&%f:%ti-AKʼnolG=znj?T%-z!Ѹ Sŷ\TJV{8Ƴ ;D]?5D$OKnhBMe-R,0c' Ȇo hԒ~ɌuB2DOuL.9_DrPtM9^57 e@+kŃ^m.Es̽h{WxtUTvgwJhQ|I}묙+?\dAIQ)h}0VUWžO0M,v+M2I23bЈ D$޼k9:keb/VW`P{l*/`xi3QhDtjۘoE)LU|R/BhBumXJ(~NK<2Is|_#-yڰF9{$%y|`=K2p=\F9dޯ1R3g9u#a#O?KM6&~a&чXyM>; ~1tBA;tyt7:4>|s>n6ćAdذ@\i1q}%Laym&t:D'.QFq.^fK8lEBxюwj1o( %E V6?P4U^Q& s/b) r-36R6:/ Z˨J`śGW&ǥh.*bU9h6((46EXfw s=W'+BWgC piVgJOl3I/pP77䞮!ȗ@|Vx,?(% s~W~%c,O#$cYq7ќHcNYwi}R)mi4b0%UF{wƏ vq{-?q ˲pn Yq xئ*/ׇ|,pgpLZ*a޹b6Z.MH)0OkPǺ8{`l$~?[\- BnH[%v|ф<1'0tUblƘ{!Q*?og,9 #y4W2-| }6QC5V;3E^IMB(Wjߐi~`8G%y{S߱F)Z$vwm<#W yf_gB}%^K/칦2#cZH(XGBxⱭT ?M1LYxb8U?&3 Kɂ%=:6n!ބ EuC1` Z |X7^̓Bߎi>uFanP}92[z=3d{q$h|l19IõSZ=MKE5E]y962Uo ڛx;Wy3\y~3"J22,96_b&W;Dp|`6I&-C:z[\<2s#f b[[)Ƨ;M5gs8L|)బ&OBn./Sˊx)>Z/R.뀮HCad-UxVTxאG` >}| "m'6k/h3E ߄%8E,ZnUtK*8쪹׎;LUScubw,ן3% CM< kg*Z:D:!tYI^l RXמF:Z:?՟Ym'j[ϴ /E_u _%L*q³}L#V95Ԃ'T](YZW:E{Ȕ9pCU:\մ vH*`U. k[ !^\r(EU#^뺙<7FEρ#|3᦭='&<\vvUOΛ*l`;x/|5WJ3Bꢺ`ʋLG/8^VlLђŎoUcw)E&ߴ 9߈G_1^[?LgVXIfJkIղ|u;trғ-M6eIbM%.˷9[jlkSx."$;ww`ȽpdL2:y_*c}=ɤH3z/ |}&Y1+3B .L>'z[]cm05c v8#;e\h(‡AgZ(wm[bXG }М os~X"+'8q3\hM()(2aV;mHÀ+QtWܗKKoc'twwNg65D( /`8- []P V-D L]jHPHd:{A9eK+{}+M gIĂDXq+g%p9rBौ7?sEL[lj*RzT9IdݤKF? go GwohnZ~.S~J$߅Oۖo\3!?JȌ#F;zyK̤@F6nxAM=G%I\{ׯy&gRISI 0 J4戌 /Qu/> stream xڍtTk6]J HwHJ 000tt4" !:DZC@@o=y[3v{ڛIGOn VÐ| ~A @^S! (_PPD ،7&zy (3M8 PsHT$&!( < &?.u˿ :+it;npH OOO~+g7~81/ A:z`70l *вr. 0p 퐞V00 #݀i/ ~п+b; h+i# @Qdu+T}Uf _ zdE< CO۠^[w[`pOg;W .0;XU/ D7fF"b l~7vVQ];T `Gfw*)@- X!0`ݟ2`*"-[8 {5r˨CɲPBVjzc1v_jf|K,!ӦZVS@-N -3O v NjL 蘥&$b$ᜃ/jK^?x Pj"ˮCV7Qԏ:iA9i H2ZjQ~*3Ip)e/1k**/1镨#rAw(VLz`& 0O%JF]P{*Nf.Ģ yRb/ԜzkީܸxT%ל>rߓX%9|M+Y!2yIgd^eB .kEAQ $-kq%D *p[`ݘ ^ MYmxQ@S]L5lm 8@ sV;ɠB3C =o;eٽ()詖j:[n<Ҡ?Y}(^i 炒y uv~H%Mx˝#`u$Ɔ͏4+>Ƅ=p^Š-2._dn?LY'nHj>_32K^h \U:$BfV3Ʒ))%DMi)L2(26 ݓEHw1Fj-\4 s#{Eą| ckw߾=h+h\-!7"ћ TvVG2DfA lض0Nv2Ai[S˞S=jml$,ؓZ*Wn3>W 1aw u|7W6uvok<$ohA#xN(!wI$Kמ!VgsS\376N 8zQůM$SI^=mYx>}>.H+|-ic|y,.S=KI$Bjz]Or޶ڑZiۨ)}\}24aI `,=V.9֒lFT 4] <7ʬ5$sW::O𻌴Q@7&ϕ3Ty; Ⱦct(XcXQWׯ疘A=Mn^aeue2[9m-aZqF|F|!@&K[wr %kG+nq1ݪN{xɳvl^8pZ#\ҸvQ%WHךՕEo z#G@ӇVF}l9fC8b'z]ץ\QjY)H&x{)?v\Gv3!vZ)i&t2˶Xg0(}5zQ>mw&0ri<=[ca]hL a676Mܣhoe;̄%&|kqo^_aШ옕b2Ӗ@W_z|]?CB*(HnmGO4Kr(c5^UsŎ(ex @1nFWu9L<#Ffcg&Qj ƼJlxj $˫n 4á̈́ թWT8H2Jތ\)N}r,2wWy>aslrAqF  W?i:, &P\)&HA!u񵊢nȋZ}_j%bc);/0%˾ڠP]Ǭ^I d*;_S*jY[7ipsNǙ)D!,j]I꩒HdbOҺ%Tte$]]{=\_pZS_;O{^O\sEߘJc)H \g a{%:_ǟ_N)oH'ND&_9_PҲ/)7m`& ;?=^SF1*,-; Rеa-w7G~ߑؒcn;"&Nk暭=];55 ;Y5xz@P|ՋސdDa& MB&Cm; '^MXQ-g* e\+(xnd+T:=c/~m%yY#ID݄{3$H_OH~5K. d\?3F\0p\GUXH4UZ]MvV5N/Qzz[>3=M gpe)fƳLNRqǗ@%Kd9 xKD#M׶Sd*DS/gE0F ,Q+&7KtŊ>Of^@,~߷G/{MwpglV#'EIbf!>wg!Of6iEGQm!oyև.K$$]pQ=BV[n-; 6U5{0,iz_nŲĥ5ą9L_lu"\7^U'T?"^'tJ{.R}c+J&1ӓi ~9ua߀JŔ{s9`{JY"VNJo60Vw$9?jE9|,94lUW)vPyw}pHmdyt\SefS U3;_VlS%_ wE>fqƙh?#Uv[VgKVd Ә2e堽%4@ѸF嚨[pQU;6X}GuȜ+m˘LvnDpN#i }"2 .x͆ϼ^а j!%CbnΤ0ÿu?)U RFt 9B;|dcw"܌uxOy7wy LwyD8ۇd$I1sl1~.wyE~G*?o3bgJ% tz$xUq'N9"ü"As P`ITb:gC%ٵG6R}N4Ypۀe[_A%WOjn@}jUe25ŽE fH ,yfe X1: 3`*o3Il_dOt:')Uy#}U8AQ'˰k뇟Ķ;v,Sɺe!Xf)19N mvI=beX(*$.|\#,npxhlX~Q\LvÑ9XkYɸth(͗z%xVC3ѳ2X?G"ϡm}m1vHZZ*!Mw*DllPzє=&c(8Ddqa oܦSdx>&Ik4 Q5{|^fݍ.w~oY|-}g6cNAUY?~t&_%jr`g8DLcqSs$S CDh#'c;1Pˬ0Y騉vOT4сX04`!}3CA'5@}'?5q&*C.<3{0wA5<آna"aa+#Biq 6o|e Ap(!祮k_(n1z((I m.ܗ>!knX; bC#[/0U|oMћǜ[.Y5ƦISreT{uq|w¹ "rA>G7c`"-KPc f1;zQl!eHU wbȷөƇXǔn=)U>,Agn* .&4hH*$/( 'GeCwqP%W4cV$a&0 ax_d^)Jyf>j„R3kaAzx'`C;Ҵ zGSr;ڱ%} ߈-&``.wL$_R2 6 .e4 a2rؕ.Joo5Re>페RZ$yJL<)&;eElXs0pݶNWxYɺkV]&S=+My}Utl3޴ę|^?92sEtendstream endobj 593 0 obj << /Filter /FlateDecode /Length1 1955 /Length2 14394 /Length3 0 /Length 15602 >> stream xڍP[ 6Kp nn \ \v{kfӶսw(HUM팁v ,̼Q9e33#33+*BC/4r~9d\,lN^.^ff+339Č\A9F- Bdn,&4.6@G-@h󾣉5@t_!-ylhn g 2 4E od#@XxXLN.@GiY=c ) W F&&v6F [sPetvwٚehddoj62~7;q#98읝@1d+{mMEllN'rW݃csgm55=-(-w¿2s3tM, a[=/{;{; d 8;}To08 [fwt+2eQWU""v/6+3Q@ɂ__i[3;?ɾWvSg0h;{6.36_wo>.kRhl@ѿ{ٽO53r@SJ;πrMA&?rd TsuX}L/ ~[|_ 0rt4@x?wbyCS `bs~w9"uM`/b0IL"n⿈/b0`/zb/0_6ZU&? |_4r\~g|`߫f|'e|ge|eG^$lyK)=QW5_)LIڿϗ%cyiwZNw?;-?;-?{n=5?{Nծ&.y:}࿟ @;au΄/ز>Vߍa<žF: תc2l MMV/>]q;5^maߒڟ_ gVfN T;xXAwP9p#+`< H7 ]W:|!F-Z7t"8{ƙe ;^`6PTc>%'ov~SGwK_ 6eZ>VҸm~YD.Sp,o:QSQ颈wj c%!|RiV[Z_#PÆdOq|\ST r0ݏ5G.͂(Jc|&z@jgT v8:r߫|k._7  ?9qܘ=o}IVuqVU{O`!??Aax}]M窞'Ȣ-^@4ѣI&)2L#c5dci,wÀ_e7a{2 oqv kJ*7\+= 45\mϜû'.'pG9(R91u]_- k5&֩5N@xNq]L'X0G9]}M߹ ڠ%ZZNJVjvdS%c p'k|u΃137܅uZLhC]nQ[|C8{%-?44=QYnM8,=06 yqٷYD/7_!XIhc")"  А51Y`;G>{ɮ .LMkUKsjq=_ἶ QlɂS%x]ᣊ %}zLaV kcw01 ’^-9m&(TkFG, L$rZ]a /G* %u߇ j-F&;nu(:.@rf6Z6sl4++ jޣ6 2韚(%~7џkɽ3wqUq_P;d);} \Y%(<0uW9H}ltFV.EF/l870|w; C'9W ݳLpyC|IϭHd~e`]uMF_"IP1xU"(W~7?aT D#Vɍd#"Tf-o]o=;FdkX1oOE]Eg4|6̪% ٿ~ԭv_>Fb|Wj^4/2ĩ.;3S:.<0 4~9Yj(> 1Ab`Pg͕ԷoEy.SB_sc c 5+r[mz:LfOPyZk*A'g_<1j 2hA,ArSUX"O< 6<dX7!bcSyAC;QjB@"Oq>\|+}x9j5a4^ rM-^8);#懬lohlD{^"vJf'BS1 $Q%dduQ:P"ƊG AÎZ G2r[ L i鋶~z;sv[0>D(v8̉cT=H-~ZOSvg+QCp9FTfH8׷PݍzӀYbRMGX',^}nw[!"6w}'q0"wv -UtR/s!q}FRU&0&TG7|8| Lm/BZ8]8-x8\FLFm(dJ𰅑1ܭQgY/Zlk{(آ==YxjN8B&I!SH2DyCto%뤡ƚ,&JkPXR VqoG"]g;<.>2>&^x6A2Էm>k%2-񨀏*k5?ytbQ!2ʦ+tmK(tX)Ö-n5[)[φJO'Qp[q.t+gc̥9k$JbɠRqg w ݞWB]2!dRxrt)r ؠi%b52/%fZ)R=Nx AĴ]١=O. \eT=4 UH7U7Ż&6^ӵ>`]d59AF!ٿ=}] Xիyߍ&2,)UMHyGAf}nPdϝh$&J2-S>Użs*N5'Dd6;|;O仆D ϵݔKc;OyR|:#Ҥ:ej]n}aS;;9 +58wPF{}P3;6CbDͺZFWbkpLzR5vϾ.М?xKydd a#Ŀ Sd0ZšcPʑ>~\(yܛ@PZ,8h@o+bA-a?JhmL2 UM=''洇~Wd+ݟ j*RaۨyOХncXFrHe;@q}<,,.inKi)#Рo, + T▏:p| P2+C_rj:3`q*J`ˌ i}_ɝ5_ vQMpSֈ*PH+؇Y 6 Qn%bV01>4}N{ 1!D^DCsYljgY \Q)ݞI { R9j*[i4q'iQ9oh< jfqM R0uƔu~S].7ksD_7sAU8Y ]GxbmIȕ %Xl T! $eRfZ³Ͽ3eIJޙGUop8>a؄ߟmlspN^⃵¡TE- vLق"oClW3HPX/_K230۝`}jcdj$Uhi#8hDg=4e\$t.,C'M+mZ+D"݉^U{%r?Z$um1^ 5ho N$:YJb&%V3)M0JX}@lxr o*NKGөJKaOLo$ti͡[yrr'[Y=/1=Kܔ&W-5kP GJ4LEhC}/B $;FOyS2웠7%mU2@گ ˼X;$PI%4;`Y$qUi>#׵k'O< ot)f9ʕ8#:ӊ%>iI ^u.bۄfJ( KF>sEg/<([&dY g So*{~2C8Ny0Hr3Q4-֟'Aw]ܷY CPG_]ǤR1InGP2Γ0+|)W0 NxD(Sb}8х藟89?If*QsY\u܆mk86i:l49ns|@!E* wW9a)"q4|M*N$'K+IjދQ$>TZJ} j5RP,9X&Y.%)3C }…c>wXr 2E\h^E'zB%uV2eV^t7M לM*s޼İ=/9(]7`WKfVmrǗ)- ʪL%vB>cgfDꉻd/`E`Vk” G4_@3ۆ5Sp>3DƯy؛ a@QE}{cC6s!=º+81Y5@\FQJ.EYϑs#[o&zΝDjz!S3gI8+Ps ^ RpO^!qʓzF«}R5_2F6C?K7#&u+Y@*'8?597&F͂v*ϕgW% 2Īf< l Tfxϴ'u85xJ]:7Ga&wؕEs 5<fuqY3, דrlc5Uit{XBl/$65Se0)"[i4y /_!F{_B@*QcA„#,CWGtV qYc͜`<}U^LNr +RmTLBЏ$ ̪",`q/ p+pY}E%)mƼӨ5p)͜+ޤEEwIJ}tWc[ͶC%C#ER:s%㳍uHU9ӵ:,rY]ζv(3}GO)ȉD1sDҔl"i7a<>b8s֭g߇b}2ވήq웛d%Ef-a#.hv~r=c\,\$h}]_/ \ow?{xFhIW,D2Nx~auI=Xq3U}i OzeIKb՘؍f eY=bxMU/ݐr/ z6 )anI`Vwh;x1 j@FD\TU`9b<3c? XN}|*5J6XIo' ≰jS!h۽i@'w)孹8޻ _S"^&E Xˎtd+jfØC3u7)UR]]Pex}Q.zgU0BNAc+tŤ91d elLiJo\]JmB)^,JzU>Ǔ8[7:>$z91Z+~5 Cs.О*.JZ@ @5ᤸKJ 4y@ y|6FW[4b u3#[7}ǚ2TT_dfS9 LhGCr`ù { ô3i[|QUJ#[P*[*{97)LպhІ:H܌/*v·&`nI6YUyi̖GEJmi^y[dj ]s'C>+u/)d/S?N_{.\A;h#޼)K|L`MBcQ'u3OlQ#^Uڷۥ[ `O(} y^$eqlX7+,_W*OS(L'3y91pk'. 'P\bo$&M:]p)mS}'d]f+ HV̨:ުԼKm>s:GE 3oDJJ}ԟaXMlp;|>җcK۷qi|t,km독edP3lsNّCʪW3 <I<,˯;Bx ?~H?%PMAKxXIOMiV}Dgm.z;BN}RV"gNgezFO_ZrGJ,Ns/ĤmA ^5A1ّAvyuSg\?Οx:щL_Sb6E{a66 ņ*J擅G5TP_rBlJ  xJz~NFQ T6urBwT+OT!aX=mmɪ8&vBC MA%ΚǓkRSSW7;C e, 3qjW5x_w> RuG&4[IY13q>+M6{Dr#ٱʑbe7Vp 2^1zKM%w6O$Nd'CO&]ko9:(J{/ϳ@xif-p`:&\3|qWKQ].;ۀiHӫ`_lJn3{<͔kl\A>uQ|_N\\.Y+d,{jemɡ״"^OM~p^;ްOJ}CEYiХJnx 0j$$sx4:`%,k* p-wK9Rz' b$$(a< Ul Rb4W3s15J$9>WlD8NQ,O33c$0*V8zA3[P4&uwQYE߸?v=a46'nz 7SIJ}-%P'Xac}1lG2nI֚MEƮ>Z@ j>B@I`9FG}#DZ[8FM;Y5p.W-~c䜾JlmUgD_-՗7\4'kQzm_ߤسMEzrcըR`c>,Jhsu=fz!=)J zx6r^<]"5V,#t-VGHRm͓iR='ʷ 9$X`N;-ƌ.KC\qB9B0Ec1O0U_~D)6'V45HSd+=,ߝCvn`6*vpyw^CH!^xg~: \:_Fa}9L7(h} o7G(1skWQ*HǻK :h@<܋>`}`y47?3{Ei _Sm:2zJM*-V#wiLh a&}HX{?*8ga |Eg`6*Mʑ_>:(DwBzKro%1Aw @@56`!rhT%6߹ym+.ޠtSie2J_RD {1^@|fC9s .-3v0#[v_4!7\$nP2_~g6*۫G=Bo 5N0Z95]zgB])yw;t20  bRr6hu]_LQ4;WQӦ #é`X Vv@# ΋D Es>lˏ]B nTN ɞ2 *tW  ! qlD…E-Ż8Vr%۹ΧslL 0xghÖ=J(ŧcu# ˌoYuq)=oQaPj@';J>DԀ%tETOW̚xц)5:%=Ni]Qfag]yh>GJ':CB|@E>UNd\;ι?J((>mZe,uab-)Q TlݟNV+czUUf [> xAzdw(hƉŭ6O9i7ntF'[>lG3Ĥ Qh]:"/(t8qN!R 1찼^m'UGH OI#]a cDF2䜙v^-}}BM?ÞcI ~(u<U[tk}"b{jueL'Ox&Ei囕hqM;Đ{pRFEʤB[ C6u\+ `VAیAt|ġn =޸f~'|;$F?; OU^v}RҴh-iC06ŕC^܌ \ 'evޢƽ~]pSCMS: !}/p<.Β`q#}QyEg\pdDI:bmR=1am#FoT ֘ EECᓗo&װeXgqEW[R״D4.RK4),gT>,44dB z]!<'(8]X XG7i͐-3--a9~4-WIWQ;c+cNY0!]/!;B"ڢEq-%ĉ,wm݋&oT OTk-pf϶C6SEx|VQw:v:}1}!{qo9MٺCLHІ=eB\vg$.d߆5,OB%o20dV"4o-ZϷ[,3O.4\nqB&0iJk(bgʼnh3 %50 +:vWa}|T[ )"mh# 5i@>AL > stream xڌeT;lp!= .-؛so0dwUw5&P&TTbgqqPSkف4(:@w;gHA9b Ptsyyll1tqH{YY .@jIW_w;[$,L/;,͝ [$#@tB +7=d zݽV;[ 5@_*Mk;8Y= <H|@/c0M/Gv/6tqr5wsX92J, /CsGzs/s;Gs ɛd]+ȃ*Yr!ZJ @+?);w%y_nlmleW)Vvn@y[AD(d6@@7Җ Z!u!쬁(~^@O"vv%`sF"Z C`iBv_f 3+gG?o4ZB`xyH߉c _BO^n =}@Fll]f~9x::mAm - d(._S tZy9d,ĝm /JdiwK99\<:jllG5KqοU@(oTigKf`ni*nn;d8>3YTvqGkkyx/UJAV"^6`8rUDW ѕ Ht?]DW/DW 4 NAkAxEdA֙{XYڹ[z:a/9$I?BrXÊM,!,]! _'?y1V\a'ῐ'd@ן]<bb#Do% $S?yCxu:"O<"?zSvr7eub dG Y g-4+r9 WG$y%n. ?HgH;? dx8{Od.Aycć΂tq'!TyB#OO`2#r|D}(.D̻?8h߾zq;Bo|Uw(#|×QJmVV:2H:ہ_m6\ K978O+nE$DZ5#]pH TH+ U~Rs T@b@UizU0@m>{[Յm67/4)? /mۥ( TOT<|HI%Ϋ Z"%3:~#j-21.0ilr\l++[v<3#Gw {nžr{!TQ 6rm-'ɻ2<&Os `-}S *;Tߌa!?$]n8LwaF]Nc1 gV:?~{UШpAFfz,TADŽ`}!V=rХ%baS0Ǒux*1Sۨ&)JMA颚z1xuaV{usy*QmI_7}pJ&GFoD1I]׺O._7nftddR1.q#Np`>%}ew0BeػwV!VpNWfC&ekVA뤾Q-8C룊D@G)җǦ]0D 0(X2y!i׊۠G:6]S}UBXi]^R/2d +YH2OF!n&It%RuG^b7پC%+#l.f{4MX꾒ri>kZBubZ%kYY&G~TȋÙLwv|5rvqxu>m)HptrZZHFWltWҐvHX'ާ–N !@-6q{&'v<%}m^.&n*C3;g2QG\uiwo?i`<ǟN2Aq r k9`L3g]'6{}ohkbjFkQQԓ&zJ3<(K^SeQq*x##2YعUC,HV| 57[,A6D(0l6#'1V3ҦY\13?xB PDPiWʓeR?YdB;gy赙a&Y[ zT UO6a ~-ŢׇG(1& @ۇ ȦiZ/JM#4v'UL3 yAhG*m EȀdi6]km?e"Nc[H3ɣDr2qmjUl:~%[[&vW aL!OB_ET'tܜIj_P&mYDJF4P24ϧK~5PpIp2滫0,8Nϝ#ё||esÏ|)/22 aXTFv~t2#_ٷټ >t%b:81-\~Pkw K4r~ؼ^ נ |DD*Ӟ;1ytF:S d 0,!np]}\hP({ʾZD vMՁ^46aia4 =tJgK1p#UwhAEǐNF/U߅xM ]˲RQ+(淳pD МpɧE 3|tL񠑺M>HNd:rswͫ;cx; ի”+{O^Μ9X_л)@bHҊ [q\o3)* ,Ǧ|DKtr !w/?$$#z^Ug^bDΩ ]3g]%77PdK(Bt_~ خ=7v5[ŠO.N]x:]u.{KY Y$3bлwRc>tIb;T0OaOU.BmfPjA"Łj$pmhl6+dˣѝr8gv>#]٠+#-b蕸gVzJi]Sz7!`G8On 49Y>AE JJ\e.෶|⹟aR S3cYڔp ?O[ 6c[z ^x rZ8N#X$bsa'zpM|YR h(-X<9D5Jo/^ݤGԊZǵ[:c҄!_\@Gx('۲Hp mimXb8x|DHU,1~usrfg'(Q {-S67*kTg}ןK sN7l*0([ŝҊNٲ12qw^|ǂu>Y~)uE0̵r %<-|z|˜!ʸ!jaJs?[qyAesjC~f OŢP{pjsly͵|-u#?.[pgZĠ.#ESI"Hއ|(yu~T|Ynzs=4ax1 P*5ڊG RyץL&0 cхLDJk`+#b: }evåp$vʍ4Ot@%jd)v܅N Y&F{ r[B1^?GGw>bꎭWHGdM3a,t#oފ~|LTE!7ڎZi޳.xr}m؜M- "#nVN׹f{}ܑyhZ z] }=YZUY )>A" ZP@Ω(E5/&mo*ߏO&?J*/5{(p-%37<"L}o\#:tz5~[noS3 %7F;+LeF]wJT[<ٸ]%#n_4*I^ -N˜ h|ǩ6℧myh:^G8}yxǼUE݊~MڏNoJ%xdī F=aw7؞Wd`蘭o9>&nX ;H;i\|%jΰ['>lfƳL`{ R 2Ng91*Dۿʖa;ğRt \V#|^We)jzɘ)0^LxiT͍2(.E~z#2~—s٠5N`cQX9$}2c]$,òԞ ROujθ3_1C5q9I\ǾKNT Н;ahE.?huʲj{| ԕW{4+{Tu*Y0=gMZomlPUXmBԇA \Yʰqzj?>JVe/q 6tqEǔonTV TCAdEn vVN{-;,A.sxbOi}4|;JqZL4/mݣb_Oۑ44K߻/ae>҅tkNP ~~d3c u=}䌶"UW )[ T_⩿-d>E@ӮוjHa~9a_㎐'Q_h$85 <ۚM+Gp )K@}֝;#7}N"'|ʘ0Kj&SQl+Zt)9ñuO\'\CR5 >N8%t iݱ߄^CUZpat6?>Wʽ6Hq '[?ϟb+;d3`TR|<#%d)tOAs+}0Fy0NѼx㠢}{}S` ~JHk3%vqfF[`כU*}߻ՇD} .,9rx[ 壡'Rr*=TRdEaVױa%ü?ǍVW=\.ħVdkH̯! 㑪Bт^?_;zJcd#9+L2e-n{ĶL#֍E@\fCa3{Qv:gFҽ̽D Z(5.Ox|([3 8~ƦJ L(ibCcɧҥiYdao۵gx!-ú36_yĎy6dp {jxxZ[%J>'/:N,\b9 8mY[}eRMv^,43[%WHK|W3P>e%a1S`VŘLM?Er"komGkGTj|q8K3]$a=@-?&כwi%+. Ab@\*C^CHG-D'WO+lP(5b*T';*d+ }?B ͊v>˞g&q<]Ir+NվaT!YDĜS0 qv=~TZ{ue:_'ߴW6AxKpn -3Ob4GlGLj`Ή/Yrˤ ;g4(BnKdR?VS S^.ADӽ3;ӆn>YJY FDwVMbwWӏ~裩z>0l]z͗xfͣJ7Zty `ZU1i¸AxwK#7|<^yjvHjt@BѸ%0DvGE =Y xqV]6ˈ\m;|Phg[͜j-JV5)DJA-"dblIQ[ uc7A?o}Z%Yh(X嚸q~b̖`N_jU](>WQ0>个yѬgXQ sqRcٶR"4:V5ئ6~e&b{#Q1|>8ϝm1B`bx%st"k1]BY (2Vwˇ_?F:3ĸn;6oʩS䒴A_h /mT"&*T^{X>wc JOT٣)jnqGeTd#ߊW5 E\8h.DJ2_֬q7 ]F wjk`GJ)T_`MtFOrZT ,~EÍ;@xR vzڄ~JO+#pp|Uh KfHskV 6T@leӓq<{{on$9N hdNġv+{f*IiD듥LgN(lzSC+{q2l>PXm bWr %? U*Wޥ0uX' X4 wo) 3r HF (h(/2׹MW}Nl%WA^sBAnt:2z.nvJR*PPJOX*KuTU-X7 0H1!M) et zaFLT)mx/7W6qp72Q jmݠ,( pJ*\QH:͕-IfFhfI=;;h"L2/t,ɆܡrYR@~k/"Iouz Va5?O J3mC"_-ֈaf1 5\x>L)BKD2RG;pq~PV4 4Zs@c2᧡}lN@iϖ9 _ +a조EZp;d%ЩizXH`}%"YʟƘ5rT3LAshṚh>krnN(bsp LRfb `c[ƣI[wh51̜VIr~=;;?9ly ]U nIPy83jbR~bәH\,;q8X3>[dޙV:xÍ^ ikQ+V>QN9&Vb>0fW`K[ NAQ5P>-6; gT;N q#x䀇ݷQ%s^;sFEMj}ZxPLn3+sGS*jں+\>1155He7dMG {ȷZ*gE}Eު NI/INLJqEa5y? MBC.p2M!RԽgv7nOw[-l^Q$;stZ͏1AB;!:}KyP9!gM]I/+;\d}B䴍~o,|/"7iH5\'IE4 P CѢi;dd>W{ݗmE}r6xwqU?XZ( ̄7AZ` Lc܇aиDe AϺR(A 2x,}L %4?hI wVg#W>[s+IhX sv@ˆ9{CIoUeњ6@$b1B'/rObt^ڠIp6d;/ tnwN2vv8ݑ)F\#fg `kҟ1ߎ!j i^` -x#:bGkTy֊ %Ͼ* pZd2*Zׇ)|%Դ6i>gb}( 0ou3]KF,ʳrQpPq{u9Ňw"x׽晗7?IDX:n6\D6(C}AouFͤЗЕê38n'$2/i) b4~xg_'ssDe4uf hdc-$w5YK0POT-Uۆ73JD_E8B$^\OWUH_.f9o׫Ԩ>3O7&Q:4~U>9 _l)7="/;W]sv0 UB ڄhI %Tրc$!bfQs8t >b J¢o{r[L5m&:L+>YMm8ʗzcaY-8l0{_wLA/5ռrބ؀zg3`X6]VGv }@%(gQk#,Z3^VpVML Ą,LBg[hLg\)9>uy P#o@E #'N,c-oj⋺țb_Ԧy3фB&5'8i'Y;7:&64M©iaECBRKo&WJ1+Ks#L8ɧCu3ZY{_I3`85 s[[[HXVьeMtu4rUddL [SK}=FҰntn,~7O[~F8D@/V=%a78A+JtI}kU` _1=Qnڳ*LS22X23nC6D?__G#GBlc-a:Nd Hg1$bd'OQUtQ'xZ }a/5E&ѸGB8yDN3Y>o`|ٱX'ZR! h),3N[f,&{CoIAchU^B_Z]fK tz} k m6~l^(vܮ`\9_Dr2te ,+uox9W335{.0ևy)QepXQѶޡt/U*bL;^!ҨKnL$S8\}W$r(Z&F~sY?4"t\!T5?0fϓ4dۚP~fGțqԎ/RuaXm!λp")2~+G_i÷AD3:EYR6k}+5 9t~SR}x܋xXAfgI`1*LǗ{"_7YNbY?}0)(R2 *vdmďhf.cnϪԧB?Ne:׃ѐVu(: ;)KHYrfmH!s&8qoT1#S0=:7*%}C= @O'm|Wh;ـgKyunJ]5߳gw;La4YrM]'C7pi6m$I}9S)\r)>)3}{#!d_U!C>YHk~NG|کZf|_ZgO\[/ȶ@ XzNwb =ō?/#lST4UD9PU6($dZVVFJ0c|23UIfx nr &^o_Gƿ(^WݜUgn-̀a^"1ԜkP.i0D|ڻD۫,×$X8;<n&3qTVdHMUt${e ͖PN84cu.(⿀q,x:%iQDfv_)!urq*ޡ*K|!b#iWyGǕٝ}#h Kջ 0< ^t ~1 ^ +՜ARAAJb/b[Υ qGZVu%0HtBkZA?ſ3_\lޕ2PV捻oCqN%pȖc9iҨB]Pj",wS'"xiWƋ(JzDۄ!n4"R35X1cay،an?BO#g 0ѿs'MYӹɦo8yvJ$+<}:\H##>/+ʱ#>Mk Wt `gʫFb F3j*O1Bt厘[Mk~[~.d)]Mmh~7)R6'ȔI-=(*!Hy0XKY}zY\{Y&©ǾYK",ͧJ7̢gQ`Bx`Qs:EYMo<*m[`* Xr x dF}ϗVF6*P%wP ivPa W؇ TV=,3>DV:*jS (5jRA" j?U3!)(D11i&55-;Y.Ő[Xs/%.`{C47xl5>*eaeZJt zmY)hl;EXЅڦCsb,FqLRtua53xo;uk r{~$Vpawj ё)ؑ_GHZvQdvvpq۾iU0/hѷ몏1I4tym.l;yiHH Y Y~%KۺĎh<Rx{F[^9t[^cM7# g}~Caș]RHEt6: /[d6G*j1"~)z_߷(`+Bs"%\'C:H.IdrB-GLǵ"C^ gq9Q-"Ԫ 4[f#fTdзZyh!KVh3x"g)p%h}U:Vy: %bȱ0#ۍ*m(p gwzMȘ]NOa~{MoXW48zSI+'5 $a(Ol. U`xd,¿8SAu!S.XosZb[PtI2Dp_~S C-n1s1-޷ctS( q7uQۄ(PYԀُޝeiQg=~nOYۣj*/%rhxv&⧍$@c)Vf &-+繙xQ(gCp36>C#cdWpk*a%ՔoKmWg,Hƥ}5&9|2O%BU6ګKRrzA>I3j4?j.Iwo "K]/ejGryz:̂qc@)@ݳ*!;mD.%_5tu[0IGVo܄"Le+%RX;rcNͿۺBo})S&E 0"DAM+'Z~5M @sg4}v؀U>cL+dnM|e"cE c) Җ:fR Su"-ХΨ̑N~ /d g#NKu~.,o;XЋ#~vsunmaS$[7r5]ξ -{xm|W:0XK},#ҭ#u?^8 QyfSj.]ޜ2m ,xإpkpfB_f!!g_KM`Ed9`ϸv66?Nŧ&9hX"m#69C>yPl-[27b.ղ9;nPʛM|(@<<1*L'H9)s5VD}ˀJ[}20z$47P .[{r0ZUC$'[RUCqzN b}o,Y.D^zw%-œ;ݗF|̶0}7eCzH Ԫ@vMQIUAsң+śX e?+lMNAyL@endstream endobj 595 0 obj << /Filter /FlateDecode /Length1 1399 /Length2 6072 /Length3 0 /Length 7032 >> stream xڍxXm>"R@:7nc`lFwtI tHH(HIM}?;v}Wu{;DA@I@!Bvvc'd7z`H0<`4S1D$  QI$%&"=$`/@GD@QJHw_3KPpz `@va2Bp}KvN|o`EA=_-tn? a FHG7 p@a\<P&;HCEE9_x CvC H7w0p8P#~p`{ w`O(@z*%FO`W"W06<MP ? Do %DEE@C,+;7!pĴ 9B1(+BP'105=`>+ F~ _W9 p)eTTD$@G Sj %{ן3.\(BB0oT+*Hmn0Fh 1oՁ:<۪cAQ4?_8 :Tnk0T`a ⊹0mbfyUïa=<ƬD T:@}~ (@1.LGᯃ`O/7 ]4О2(䤫z[/mgRdV&gv= 1mKj3_c6EZZaxA/53k4B}s<^P u \|3EQ}8+ =;M]ϑ{|_ê!NZt D!B;svvR^j#7QEk!m򓦃 qۻԤ,%'XLI 猵7t ,$#BH(\*}T&E&C<8qtC`/~AϷ[6GB6Z]veɰ-E#٥&A '~{i9Șjb3cG ~XMr5^՜$Ҧq*jqڂֱ\zVʇʀ;k5:!8D1_'„fXΎ̈́p9EVlZ.܏z?R3 jAoI\O hw!rN+n岓"E*GBkBkZ+ ):ʡOv$٥]&֤ikY?kc:3)䍆+]XJK{#gἎy:wrփ`֕nQd`eZzCS,_LIՐ-zL*헬AOy{heӷM}jP-:f+B)ԬJ57]A6LnlxՖ*Ӑ~W*=^f,_ZYU֪o94 2Kp HmGH;]P';74.m+r(J4\ >ߓBM5*FQD{^ƭ [3hfGݑ^L|627lR#wڰ+3!E2G#B릊 go4;E} J[#bӟI" "Ԉ/S Q8nGOؐ+;8^/^Uٙ |5rT:]Z|>\,V{NV}W=U&pHGK4]e?iwd{KckrqxFKT+GDkU㍾0 JD uhkTVƕ Q,q bb1x &;~5rZw?8?fr`H`:cu<Z\k4_I[u̎V}j[-[ߨ6}>6 ȱ>ݒ#?GӲDS~xؖnmH6g1p?'xp!zZ2s{`kY•ȗ"7 !k;~<SkӼ QP1zs* pȾsW]&W[ ۮ xˆ\gmɀ W{nXcptmT5O(Ғ{ݽs\\ܗI|bf`.z>:4'jA_qK`UM4t ߺ T@*>7`ktrZy5\,Lˑoɣv_?g(s@)W7moF}!)^ˈXIUݛ-.[NWcެͷ(Dûԯ C}Pc:ELtP[JVԭ2$cGHZ}3 6> ^{P/DpeC˛¡iq'E2.$xA_ ϣ"rCbdbR,ۏ~N,1<ϐmXӷ\~-A'ky8}LpP <٭'6 :}#f`-Kn}nL?y-+`tqj9όEƅXg "תq.@?JL+wƾLWlELjh7//Fk LߋJW|O]X{*OU,Ci1v1MGpZ=sɯ]9(.JQGS`s5 %;cߦ,0ޥ:I yBs.Hg7n_x£?bHK|.dY޸e@ ˏI~N*o]<J3rK"OדSR/P:pm,鋁 kqUаѹ n6*"sD4Qc4y"]x9 <_y~ϝJtIMHta/J:d;TŶ ̠uR\Õ[Y$壯\ Ne5 Cdt/"ot#[pɲ.l=u-@]`}Ī'){^Xu2$S:́!GQO. xRv3T&%?]Pg5xXLБ>eS-plJ/~;R]U=gp@1lPMk^߹!HѪGcv'&D Șoiʑ`@z:3=*}SY4q.А4 }U]!W" SSLI0NNi֢\RBα7I3:)JrɑdYWnE(M%-3H_ѐ+`1.~޻yfb<VS4NEVqO&)||qu:`|>`gڱrT^Z,I GulY="7XWhH4.qjު/;p:%PݔA'AH\ܬJ>UɆ]Utbr8`*#6){1(tpYD͑Eec94pU?]v>wk}"Mw{ Y~\"U# (\̳w,*}OT吴}.5ď/$J)$U Q-hrYcdg.;»Yl% J6t!rvn09ߴ+?&nߩ!C3TYiГ/fI[&F6{GFG7Wl+t* `-k|z-:Ii&Uڲ{85b]%Mv4*Y;VY\0(vcz*߸#όA - cִg>8ED_(u+k1ѽvrv,5 ڍ~f!U&\elEDwaܲt9\Hi,Ux T:#Paώ?R?Y斯lQ̺eJ&+RUgI*ڋUY8|ڎnWD;w(Y\y35+`8EvQ;1tZl~zIuzBd=>ovz+:Mv\]UsZ4|gz=QCRWpFw8mt)t{KpbiU%+P'a 4U䂷oUfyIOYZ5Ӧ} ӣ:#3@2Rj]¸ͫsj<5 ?T2hXrdAhEv3&iɔ7Xɂ K-Um.b4%gB{y![< hcB? G34\endstream endobj 596 0 obj << /Filter /FlateDecode /Length1 1612 /Length2 9356 /Length3 0 /Length 10408 >> stream xڍP.wŝ] (Nq-Z(nݽS\_};IgZoBKVUb]X98R* \n6.dZZMo926 B h"6uy1TvNn''CoC@ dPa(B@gdZ)%ߏsF ? { P1uڿd47h@A@ b fjqcd\@ge=ؐi ?KwS' E`2_\\@'Kv2,dOp657;=A`+%x#0[64sL^ ( +0}͝@.l =2fvqF]4 h2wO q{,A` mX:kA@l^DȬ.^.A0f@_o /l8}o ̀V 0?_@?;</pa?1_-G)) xrXx9~^yk |_ X ݀w+"YW;?  ;Ͽ,^*]UZ\Wb `Frq)9˂<oA.O}o!Π7̋^q~*w^9qLL=9^ |J d!./.}''`-seAvЋ-9A^;_Pn/ / /`w; $r|i_?>/qy@sYpMMp˯* wQ.KD-"]@) y靨5C[]|[U(!xKMqlѻCgeWv=n7~S,g3r"t߾TX?bCzE( *EZbjMD2Ԟ!.ލRhz*eƁا.>b%qV ˖3a oqlʉ->:s 0G列%Z2icu᜼ŦLSRfā@W\\k|Pa0g@\+ɢiQiB3m1Kv,91k[X^)ThL[rK-KN س_FʭӔo=zJ'r{5e|b́J] FZxgzgV p"=W***!ʠW$j*B *of|hJ<)$]<+5|r`/ԦNFŕvf!fc RuMϖ9)~Jxs;LBLYl{(_ '+uͦ8*}*?'j|vJMՍ17(ju8o ˶{uPmwiU(h7yBWֈ/l-MqvI;P ,+AN'u' ̇*H)exPobN(EY;jnS('ȑ+m@sc乳`DX4ѣεjv57H%0 ⁺MOd- EuQ&.fX5H ޿k ~g ؘuw?yC nkO3 G/ _Vl:T;;x8t>(nC?(uZ._X*7̭)1m."lK0xJ=mz\C%3 #_N5XahR}LJ幯 C'ŗ}DVF{z#X95-pz䧘(%Viu%4p"nC01l2!l;}:?/E[]UM8 _nVy-+~&Ã9sGHu;O? chW=pƍՋǠm-A)OF1ȿq+ɝc}<'Jmї:=:Ŧrłct8}SkFUԶU$`Eŭ  BT;GKD[KuO֏|xZ0m"4bGax/v  RIPXލ^*=CZAO@-<|㱷W$kjDp#l]P.̮xfAN43<lK81_8~0MWRUߣ@G[DP) "I] xU{But@0z0;d1] S·v''z`z©uiɞ3(b!9pj~`/Y-ڜ\ɾ(q(~OU\j|)N K9nZ=]/ȇNd8VT??8Y֙oTI#J~.Fs(}+ˎr;ɗxS>!ޥ㍀6O7Bx'>ܤvJqHT^ѧ%!bv$ Ȗ~Fh{j_T/[G[7 !jqO$7ith$k7M%XP'p'v@eC)*ධ=*{#*̊9m74bp͕pn *{melj0{n:3sĄ`qs1eU[{# rC_#>_UJ>,M]Fi'_ ؖӭE7HnFK'fAyg> Ӗ/ VO1!Ô=y78:O!'-thIltқag) W-\Zc S 3_ԨSZ]: |8Pp<{}SopbMjW,Vw7K?pկ{=@8z/`W$-\{vSxH +S4`ğl_EҧD+Q1*њ703Hña9B+&lEg ]꺆|SO1P-:'p}ZCجqQ[]M|&V_f(xX@pE me4r:(9x7aͭo-DqDSGz̢V߁AwKc0~XAw-t ԃHeeT9nԵjmuîkȼGT5#&As\T +U13Ff&zCm;㠡ze~-`Ir>5uw0m ÿ9:AK{rNeZrTegV1CLȋ (L;S;COD(w3ͮƙ˩h1Ѹ Ǝ@/7 o}p,hF&Lܛ*Tn<+1,)Pp, 'loWp9r7KS U:t 9[ZfǙ]͖1&gnY޷!{2U‹&Lf}e7SݭH,1.iZqRL&C]FCwْ^$VKgrP!&S*.TJˆrhPL/nЅ}ee>x]Lub%ϯZ:"%sc3*;dH^=k&~c>d[Lk,PA&J zf|<ཧe@ \(n{%ardv&>{%aO ŽN򓏳Ur gjt]۝E&jpt6.ISK<$/ĕA{otQ~0o!ݱf5=bblͿ4P8z0 SM|u_эplA9f)^f3/æ~gT#3Ҙ#=QmηG?8Ҝ;RL7K!0|ysvc|}`\jQw7溊xu%}{clk,`.}?q9b$?P x Pֿ3;k/l;Gu?Z-)U{(.S7ՌmPl$5cɸkb3+\r,S7F.`ϖ,iBl ffQ,~N8qXoBпS5ǙT~X.u} 4c7(wjZ!{Es3Ac%YJ"KFw7S<ܢW+?\ȸ`ZRJi tMd|\2 #Cw<ϧiW$2?<ϝm,[9&h 4:0Z)+!qG@Ј7{`VưX .>AL-{ήc0_'Ʊ[%}p9p9łO!n{~N7@v(i2ȓ-C(:`ŭFG/I4NoW\s6.}=l2m6T&?&ܰНe, )x@vw-=2Fb:ޣJ`ϧ$u+35 ( -UҔP2^ͩpxĦr,3=k(1ZG᷼{d{'􊓕 9aOrJDǖv7)!#b,.^P`#Tv1.3iyBb+קa3l:]9/m<`bc.;Hխ1Eq6j-t{䙫]f՛d7~{Gi;U_TIMȫWCre$> 4j%N@w~ 2_{Z0lAyVD q]bȢ%*8Kvć='Eeˑit('rRVdVtԞNf4+@E]% LƎ|ZP .^,穟'ہH6jjeѷY ڴq) IC={ϦIcӃSR hҰet46H Dw~@[׆CzD`}[z&jG\+B4=٠bՃ1F2 B-%5w5QaZcDŽ1 Oû8Bl MbH~`#eá}^@Qv_ȬhB\0K@p ;-n|DYAsN7Ӳ#'GV3znѰѫc<ԘKHėV#ȡBs< ޛh*l<׮yVNP29qۗ:rj6BeJa'r0Ly}%դtڎ\ Y77</Eҽ?=@?@KۂEJ:]Pb D$pj{g81F#Ϲ4WHiIi6>߮ܽjX?-ʢd@R09{F]mJ=0Bnx|f5< RxUZTa|4 ŞnbUqwŻY8jPk(z">XeIW3Ȥzg4PP\^G]d .Ya*d,;WiAY"@e"6fzVZ=u,EjMY\4ߤ֍uIOMUHѴ?pt?~ϰ6xriE~0ȨQ\SqMvK .~ޚ_xO~39/vQ+8;p-vҗ,KaUi932\`'%ms0A)0d&Luj&qjBZ 1vՁ;#N7[GAa+(h`\۬ "O>t+)YHQyN*ԏh,~q&pOOdԙgkQ"*)t7|s3F ϥ0_DGx?"%1j#RəW{$nKn\횶6ZH^!r~I3Oy=Vf0x׻ƶPGS !_].N<^FK`;{ѳő[[c%,ρ Oe3ܨ@RoaJW NXU,&NwڕQ$8_Rtu2z$Z^#K}Vh3 %k ҭ{-w!aTk6P;ms׌rI4׏mzEʦGmjľXG"9>]LO:ڦ ӌf,FQdUo*MM7BB $;e.*R5? uJ; 3UM4l*K؜Pn״pPې~J2u*|mo!C:x.*/WDMc+=;hfqvtaos&o|*bCwLp.);u .ΓvQmwAaZµgʮ)Y$wJvnj}k6)6Yn ݥ4v`ٌJ8fՁPԫ_~GU|>djJg;M7iy/ k__83owZg@%!J2?Hpeès܃G,L>yJq#!9R f1< ᦣLig[s7cI&Ө.:\lK5t.ې٭C4%*iUd_ TT~0%FKE_܌<@I}e+ grYkH.Ȗ G%ل IirItk)?`oz:I ZYJu:=)yWZkE$yL:/%EqY@Y 6o|6jv^$ka+Kjk i~w1tP+96>|QWX66`YQe>\>v+卮U]a u"[>N`B*Ó;<7xh ݄筺a>X\̰Dؼ1mhN$M,gT Q.Ԏu>1EMw`c ^ aΝsK8uz[GpD!o^D՜9{ *|D1ZhCMr~{G48Lb(F9IYCbPILuOIO!+\.Ave$rہzQbdJ[RFF~(a)i;.,5zVoFD8qZ E] Q QZv6WdV؋(f1i|L[6 Ј/̍fE^鵫>qXәՔ ZJl?n#~'6bV[z7F_Og#Я FW\>_Gv89\б:7fFF(:Ughiɚ8%FB#,=7JJ[ Su}?,S}li,xu߯!V._|/Y/ cQvY2se$&2Gk Y44DQ=CV" ӼRl&t3җ$uxT|l`N}N+KEb;yLL_$}b.q{=5ϐA !dshOP64FAb9k#xoF)v]R2$rk_=J،IXZ(G.Hlhw[&dػsUhY֍uĩfCϱS[зfgֲ=ێt{CTiZqt`q=SakcOVґwXfJX%||7d- À37~\FrsCd*p;v?)L6͊bL0pdZ$WP5^N:~}ȮH!PVgNF"KЁ3dmPDƍll"tFPKo[v|ܖ[ W^@{p7_g3\R]nszw v]j]o?rny9ߞV9Qy7\Rm>pkTia #3( qlN Mwʯ__Գ &X^S'SE&(bl5^mnTRm8ID8DޫAG:v,[N DQ> 1Vendstream endobj 597 0 obj << /Filter /FlateDecode /Length1 1463 /Length2 2100 /Length3 0 /Length 3029 >> stream xڍT 8TmN+7Qc6Fl=303X}i3QP)*E"El CA__9>]גA("ԥÃBdLⴴ<`!iEBX!f13.1e1 d7 70 8@5 !η_gJX: 0ga+2\2aHK )G(H"Q*BC td&F#ⴀQPCspa&:pwky2v D%3L4@aa.:aB` ,)X>#s~`ut l‰L> +$-m ²F D(I[ !&ᤉ DPb-#C~s~!!dC==(!IAcAԍCyEl"P!PTρ_-X0S !?(,}` c7|It/#ZYa RtzFF4kW<G=Fx.}k8t y_ko!Aso2^c)*wd3`nmӀ3) b!AG L ?F[8 bB&guRqarEf2&.f v{0J L;h0QTdT`pcFL,(lĀDDP!GJHEq& ɤﻩoYء & Hac/]3C|LcFf1qkQIl@~,tSvKd=lTB_X eY?y5zkQ!iZeߟ.!O'~CC=ɱi.Z<)_*{pmj*EAn>K(IZ@!jYq>Fr56'菉*cdZh~qo~݃ܳz_8Yɞ§s_5ݠkV 4 8nu_{gu(ʴ^S.8@miF붎f,QĤ304Y~&㰖i~R>^332H_9uɻfdz1S֊Σϡ3╕8mi``šʏ?ʕ4|FBIDX2@X~'8r5 Ջ%]꛲Ip4BW¸ q"7T>]`r~G9UޯP2ֈĄEv/V]д\Hqe sW{Eک%51_Α{]zC:Zoi3K*_:mY~)y&aUCYJ.8\IZMt]kI#Uʖ7-+%.K^؉vbeGoUm d`f?IF%ҫr:zM/Teя%ٗ}Sj}n{;IF1 FMv"[ү՘j}h(9d~=^fƒꩍSvO?y=y [>ʿF‰ !2MK͘ro,"qe ΩwY$m 5ݥ2MQ]6w]~6:e5}uM_s*Jz*b;d }Oӫ{Mc (\JaIZxb!≊ ?FЬv s3rgKpQfr#)k}l{Ξ1iro5.~ۍ/;n_[[n0=.U[qP:f^Wv˫"3p_F̭Osgyq OAS'$+ꇝm򋟩4&?ex'H"=U=|[)iXP^sD-:G03~ml~~/w >EEݸ}ZӔ%Kb֖yʓ_OpU \G>btrNl?mH<|``H˯M6s?%5PIiȲjkh2 uYbZ@Iɡ6*ցdo4 :dpa#*W;z _C/7{V6W68KzK>.[YDq\ӿc]Lp2>Gd`@;Hȥxrڥ;JڪO.feUш{x=dT䌌ʛkK;'›\''Cs&䙽.\hү!GSyߵ׷zJV5K;}x!Q׀5v7sP9‡ o~ 3ޝ4a3̫+}~Wssd:6fYTW?WD8ZLz!I[}| "|j.89!fze[qgο:Iendstream endobj 598 0 obj << /BBox [ 0 0 611.999983 791.999983 ] /Filter /FlateDecode /FormType 1 /Group 205 0 R /PTEX.FileName (./protobuf-distributed-system.pdf) /PTEX.InfoDict 204 0 R /PTEX.PageNumber 1 /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /Font << /f-0-0 206 0 R >> >> /Subtype /Form /Type /XObject /Length 894 >> stream xVK1 W`;oiBBT8v B,pc5S^t2c;/nCb3l7C?>=§!"A*s( Nu KrK$/bGCU͍VFwM o0C`1gOu#a=ۙbCJ$!h~d)C^rݝyzd߈ao7(OR*O6`gu?SYVs???^آnr-ۮ+>uٟi1uAIr;*MGԍ J xYƮN{4ss7 2 (K}7Z ^U;:44~[<9(0z[vF+ɲ Ko2rq$',cʂYnI6!pOVuhMRzBNUgt;uuo2] cZqeXP#r0tu`3RvE8h|Gŏ!b HY"ls!0D"qFJ"1S)2yKgd8UQѥ4' bo,% i36aR8,]YI ~|ۿZP^Dz>Q=dؿ'iH@ :U,*2hrd,DGet dZ*ٲW .v}:.Ǯ$DRCpfqSvg#{IsA9"/g<ίD(ܬN衺7MC0X,\&_pUGC,&.(ݴdi֌vF2DW0q>Ɣ0 }jII^Wendstream endobj 599 0 obj << /Filter /FlateDecode /Length 4266 >> stream xڭ[[۶~[3Coq{'m+QZ$UQf{ȥN'|ExW߼ɳEGU\%ERjQdETlam]<ʘt=|o6Os?گ_}GU(wiwNf#}tώ;ܷPo$#΍)#Y=NtϺCC}Oi+-kI<ɤ5΋cݧ3~܋4\e0:x$q ;ݞ$ȣW:r| (ZZag(+G^ mZ~2)'ALIiϤ|D6$ 6#鈯u*eÞ8)C߱_-Ψ4d֝7V8x-,#: iEqUK$%tpXF"s'Q<"}ߚoc=')8"UeG⟚]i=-8ƾG,NaqFmU4YInbUQ]l**YD Y<?uWrVc|b j5sV?gM\EI=o(=;5hZiޠq\4d_j3!&l F(p(E8ݔ4+MqĜS{p?.h8p~0msU*3# _H%ݰq0󪁛qy|-nV^foYn?l9*"uaͭuᏌ@ A=fAXA4?܀AݨYq9Y2HuwR!Vy:3Ny;x(+1w*eLw'LYiźlMFj(Lm ЂK €|91]N9]faěj,Fhm`tSئa3Nફª4nElFcۜ=ƓS (R(GOA˜ -e-xo~kx£X0l 5 N:m;

5^za&| *vok ǘm`ݱ N w(X)mv Ć)y1  R%`\b0rkU0f-PJzY7pRZE#7bfbDj[kү~'"yS2z#ʝ <4#N kO⃟u`˧"2DQ2dJ޷BzoqO@$хt8ݟB.lȦv)([rt a!afs]7[XNM')L!g ]z.}o8F47\p@U[Ao|N[0Dzi,*rx+fGQbT;0 FLe_/*m.Ϗ@UyM@;X7.Am8i[mдsj@1p*FM+ ^.}Gq/>18n?6IwUȲݮi\-rfz1ʹ{J|VH֥qi ^L6kT2y@D־4z]Y cb>5x5T]w5;@# eoVyH DrFOkLݦ ܿbZ'n`B* $y8$Uo$"H<]%(k8XIt' FW賣yx5k\/l2w}TgTe^tzX3\##d3;b(O.L{pk bkn@bpR:-t`+G)cLp]d5@xZi}^ *{HcOoWi/+Fy 24>c,o%Kq^#h=ƺe ַ@r]c75li $>Ps#5brWbf܋މ.fmol5E8!){Yyzp!f$ ʫR8"9ˌIhݼrրz`lO2,=j5b9 vX̒8SBdjڱ;zn$}3S 7Q (isYD̓V& ꍀ[UDB^6 "<`=dn>r!%pUkM|84v:A8z}:2|] g>[Zf.[qv؆04krS'\p4MVf|B{0tqVԭ -VCim㜼7}M|eVS@h3nǒjИfaed?v+OK#吝u4FKMO̞LuLХ'е `wB3]64[ޅ m -{+EJֆnf ^ҥQ3p%|H+CT s\>,}ֲ@J:˭Ъ+ó 3H>]jǓ,77O={ƌ䳮4&)&W,XhBޔ^gRLi/l/t!"0sb2#6tdZl7-湉b;\9S+vʍ4G,s30ԉ}yzQj? -~ |u:072u.oQ~endstream endobj 600 0 obj << /BBox [ 0 0 432 432 ] /Filter /FlateDecode /FormType 1 /PTEX.FileName (/tmp/Rbuild5569202a0e92/RProtoBuf/vignettes/figures/fig-SER.pdf) /PTEX.InfoDict 514 0 R /PTEX.PageNumber 1 /Resources << /ColorSpace << /sRGB 517 0 R >> /ExtGState << >> /Font << /F1 515 0 R /F2 516 0 R >> /ProcSet [ /PDF /Text ] >> /Subtype /Form /Type /XObject /Length 3950 >> stream x[O 律}D_hb=9l`׎N=RqRxJGJ/7}j{Ǹ"{[HuOy}{uۯlɕߝs}_^ճo6}{/wW _>{z=^%+4u/en{z=}=_o{ov[e%.,[&x7InKܛj ~7 {=Kѯؽmdm5o/67$ÇG ^+]Ƿ|˻|;" &v@eoUݯD;P-,>yic8i{\7,_v-i+^W--W8 Z8l;mkc @]v w:lX@!GOqw X[ q9¾G NB ?6dO+n[ 6R^ QVLNiebKQI+^*;tVB Iw y 65 V>%1RYBVp&W7\ $Nd+t3WjXz; q$mLZPNfV#[ ;SdPZDB gPDh#njosȌDkcZf}r^W㣛h%-K@;Z A ؕų=,^KOm|;<[m)D6."8ݴsNVtpyLU4 @]حhu+(  N$QZʭu@YZ:(eے2R_J ^R )!sKE{EV %dVs` .5Xt%̬WE, G5\[is9eZ-`TQL_iraZ-m'7cZ#) J.)s YaCX:b.۠!'< XRR=}]DIP8r g@X>Nۓ{gxܟl4B'Qt̟:\ kؿ8(nH~XGO^?>AMw7_mO~b{r,t{W|[d^@-׷g?|f{W_Gǁ^v=!XW&I&y3HՐ`dtyxwVи bUG8G8ɳΐyS(0Cz5 '60$I> P* 4X`D3C> U73ghJ v#"KI+m0.&Wd6EcMB!9;X{%wj9 ZJrY >\%kӐ fk`"uiaJQK^-XO3?xxRwZiOI_gV@^]YDo͓!+2< zj,wg}:-Ez\@t:˳d$06yCh'D<(I> ɮMüಽ3ȳ~EжtSKуP#*^K'yַP֣dc( p_8Y_gtpD4bBw˺{F okz> [CsKӑN?vjbDjRfy7NZzyu ; <[lC=b^Yߐ"kSX lg}aKD1 .Gd1 ;䓾 4 MnǀY+6|k=RJ_ゑTwI>_BtNW6aT'oY/fYH4v80ɳ͠)8apZQ\dPI>6FoeMc30'}IwD i Q9?'}I/()f%,0UA #}xozȳ<H YSaXIء_ہ|] nOq2זqXe/If ƒTEdabЯ8Y߾"jرcgV{b/Bb)ZOO0݋0yַgX.@yg})둁VB5d/7˳>g^,Gh ZWb^ VK>9ɳz5Zydf~RXtgg}NY+ͭl"Nfݴ//o>$ԼGMË&IGdieH, iC>XP| q=ttO~r95,%QpWZ2&r?Y0sVz\x=ˡY/uP%>E>GiUգZK2CGƉ{0)qi<>IA(tՇ< Y 5ٱ"Vqp6˳ij/r:OV_/Cx5`=[7x4mgчR8') |LUI쁈VV4'}  #?[E>`~ჷ<^ί:Y_VE{^@Z{&"ʡI-t9twMָg}Ruk%&$^R8YtY 6- ~҂X.?:9E-=#H?OurYRe܅kfعېO}QڋY"I}2:lo>شdY_K3d^vuV;7Z!գ_gNb&R2\|ҿ,ְE;M{- N['onQ#jp'/6z)5o4Do=QnI͎& iu8nM[y;IAu!/sZIQ`TSJ_E>N&e4_Gfeg}[%0|Kg2'} ibu7f嬵٨uo.?QNGF?jGé};ZE@+}{sȳ,:8F:Y8\uNN@:C>.לeڹ\?*f9mDMȻ6S4!0xl[.0$;P;nng/7xt';H|~9{wJ] hc7?\޼Cn)|f^߼n/ ._?'{=?ٕ0^VYGD-V WOt߶uO=-콉 ~?|}o߾vWW7endstream endobj 601 0 obj << /Filter /FlateDecode /Length 2198 >> stream xڥYKs6W2UR!^2LUz|@$:zqowA25%t NY],uk[ܶ4_nx.YTФ|iL{U e1az?re/VAϥ׳ݱU*VU0d_/]pTB +a5Hni(oUuO7.u!/eE)g-L47'P2-&b'K-Vջ׀V6ydt*n0E0wPdIbr&(8g4 E⵵d,O9 ?4ƻmrJ@s'VJaU, آ+D!`[7[O[jֵqY 4|G@D[!ؔ[C C,K#$J2"-ǸO'caXcedϥ-Haa@tȩ]"gTYs^3UrUJauˆG~ŜDF "/Sh2Fâl9 50]uœS׵q3qspS>*g]}UWN+ O)`dFБb!sfXs,2fksg5'itѿ9 qimvڔ^VVH(Wn!UѾRalghJ9RRTn &]&w]RMFѤZO S@[TK袰3e4vOn6Wu>fȐZé;\FUP5?bR͎R4Lpz!W)բD'`Pܩ](\@EYG@AI7_XІ^Kk,,i"޷iz,a<4rnCj4d٠ITM "z@<=~[Hz#K c2͙oj%yUC=CsYmZ<\dũH/t`RC/g$SjG\bt cm%.!m4uw%B>|aa9]jDSJ mYQaW-g+g_ݡcUif1V51dqD E{ܸvZxD٨Yussӹb1 -w@\i7PLJG Ep4|b;8 w>X i'·]R0ܧcMGGN-I^GG`#E'N4myKx^ĀÂx*!Cح1Z <^+hlq>/qaV{$>/ Y, :& HPAz#k/dѤ[FnۘUݭC %,'QwC%~&>o%I*7gnq R$β;L~M*a&1qM~V63H8Ȍ .VCladgMDi޿%.Sh?MӇk+6= NN~8m n{.8Vy;nXS8hN RBF:qތz$9sЗ"Sg߸p$ܑp =#OUy!d S3v ]\ 3321KTL9Pa*i2="=]0| o`JF*zkx5|= au⮭ ^j],@= +w?Oa2ua?Qz8PDdU(o-}'ߋ O {a[{OA^-!o=ԄaI/t>OMXklLӍp=?c_"dtDK.n "> stream xwTSϽ7PkhRH H.*1 J"6DTpDQ2(C"QDqpId߼y͛~kg}ֺLX Xňg` lpBF|،l *?Y"1P\8=W%Oɘ4M0J"Y2Vs,[|e92<se'9`2&ctI@o|N6(.sSdl-c(2-yH_/XZ.$&\SM07#1ؙYrfYym";8980m-m(]v^DW~ emi]P`/u}q|^R,g+\Kk)/C_|Rax8t1C^7nfzDp 柇u$/ED˦L L[B@ٹЖX!@~(* {d+} G͋љς}WL$cGD2QZ4 E@@A(q`1D `'u46ptc48.`R0) @Rt CXCP%CBH@Rf[(t CQhz#0 Zl`O828.p|O×X ?:0FBx$ !i@ڐH[EE1PL ⢖V6QP>U(j MFkt,:.FW8c1L&ӎ9ƌaX: rbl1 {{{;}#tp8_\8"Ey.,X%%Gщ1-9ҀKl.oo/O$&'=JvMޞxǥ{=Vs\x ‰N柜>ucKz=s/ol|ϝ?y ^d]ps~:;/;]7|WpQoH!ɻVsnYs}ҽ~4] =>=:`;cܱ'?e~!ańD#G&}'/?^xI֓?+\wx20;5\ӯ_etWf^Qs-mw3+?~O~endstream endobj 603 0 obj << /BBox [ 0 0 701 390 ] /Filter /FlateDecode /FormType 1 /PTEX.FileName (/tmp/Rbuild5569202a0e92/RProtoBuf/vignettes/figures/histogram-mapreduce-diag1.pdf) /PTEX.InfoDict 522 0 R /PTEX.PageNumber 1 /Resources << /ColorSpace << /Cs1 523 0 R /Cs2 524 0 R >> /Font << /TT1.0 526 0 R /TT2.0 525 0 R >> /ProcSet [ /PDF /Text ] >> /Subtype /Form /Type /XObject /Length 3946 >> stream x՛I +8)">TQOI\^@xo:0TΣ2$;I,I^[w2U Xa~le1a1<Ő'[Լ3B=b^\ˢd^y (SԼ.,j^3{l춳} NN)%6Њ V}e)VSSAa_8S"$dETH1㈏^H ZlH=%-TE,IF٦bEI6e ٳ(?30>WaVԊ8O͈bEXQ~^KV%F+ jEZQV9 (YQ?y#Ŋa,V]‹]YB\i} RqlEnAiWbј$+1a ɊDf@يbE7=b)GdŊ"`\ۤo͌HB]*Q$F1*Fل`顄,>&\b-&e@Dt<Cl2ۮA7zapMtI׸5kkgn^onI楹߿3OO71skrIe7!(=e,vSw*]I]:qu7-b̖,:'ahf|}B2&Ү$By]!#C^o[/ r` r uO  9ls1 K\ Αh. (pc[ N~$BR"SLg$*PAx'(B@9gn%gkr0aGp4f̧qgޗś/?/-| :1up >?#,Ͻ˜prÿnwBX| ,֋7"t7: VO{\=Ǎ?3?<ϹXRLxuWw'R}UTFFIJݶ^={sj;HX[41WEω*:3W'@' ~JޱvpݗloHTēPIs:0/0b[@D2sVݜ^s4 $b*x۴[mQۆ IR53uZ!%6xLztʁW|6s3 krBa~%XE"cDV%[{"zLY0_Vzޏ'ɴ0DcD`sӊa{.P-Sx%WhzA^%6.]b/ #Dݕ._0_wkCe+8.NrŽK +f IҊD;!)Le]qZv#wNgκsK .Q7>5\8\NS.,\4D-**;1 2UF:'e9ՅXnLc,%vBVݬNсH1%35 'x|Q*TFH`@h IrNſT@)▵lr}GǚJJo#g*IOJ9')OiE݉7J @!rXel7D7x9h`^36L(C,In0d؊=tLn54Y9_jNB_1"7+̵i]u1W䳧mZ ^񝴆nQf~%# JqJ!b\+{<-J;5ܰ(1e-t$cmֱ6Ig. O8 '5L:YqT"a=V}WuMʑIÁ=Mp͵31kwC> stream xڥے6=_ə!^˒%R07nbIe=7,0;#/8Xqrl:i(sLLMENpz<: _x>~YI>楯op>8qCzdnޤWT lavqTʵvM0F4bat[@.ŀ UI\j7y~㞴<(RwY`\0'"́B"OctbŎg%_#l?o.Leٽ",DԢhPJEy|,D9p"4_g#o]Ɓr[k+VzҲdyfkuxyvxZÀёuRJe#X&0K^$|}':PL%cDq<!m &#~M w«L PU#YȄxP]Og%-xc}(@b, BTB|m0!n$Kb]1cSТX$xpV6f 8&t9)П)[?@<{U!vGMQ8/@6Mc\; ~I>Pm~7PV ݃'Ťlali(7DL,䁵~IPm`ȓ;Z2'SBF.ӆҋU-"pX8SlƜȚ{Hk%!s`&-'5I*a= ~ ٰb^ $}sBTΙTϫWJ'őC@[zb+[j74*"b.h9cRz$=JX< k s6(lq{bBn;96в< )J43#{=gH*~jyPs}1B V|Ӹd\|KgCB{>AdHTR8d0Y+˰\x`BF*W8:b_!Jtză 7>pjYΪ-/}vC(M%ÈǽqQC䓶vJUᓡX}=<6w m^h;MX9_,KsLjU/X_Je1~ia/ź3Ͷu`0zpJ]K>!lI!qΠ%fѡ)|Gfn}{}T< 4 ZL<?t4=uejqE"k.ӑ 89 :1؁|HNܯϠ*@VidX^bφ<թ =cfsɞ5/z3c0&CyFY5qHMkkD=[, h`/$:Vc .")SK=Y6⨢Zh9DRDv ЅxSG@AcS7. `_}ͮڍ8-UY޷PE*֝8 _g!E*toiҶ*b{Xd.$Yk r‚ rqNXr"l8' n( qͺo( ߾igI `Ο/64y\ԉΒD=_\Gok k cz (iZR^Ie߀Caendstream endobj 605 0 obj << /Alternate /DeviceRGB /Filter /FlateDecode /N 3 /Length 1047 >> stream xUoT>oR? XGůUS[IJ*$:7鶪O{7@Hkk?<kktq݋m6nƶد-mR;`zv x#=\% oYRڱ#&?>ҹЪn_;j;$}*}+(}'}/LtY"$].9⦅%{_a݊]hk5'SN{<_ t jM{-4%TńtY۟R6#v\喊x:'HO3^&0::m,L%3:qVE t]~Iv6Wٯ) |ʸ2]G4(6w‹$"AEv m[D;Vh[}چN|3HS:KtxU'D;77;_"e?Yqxendstream endobj 606 0 obj << /Alternate /DeviceGray /Filter /FlateDecode /N 1 /Length 1088 >> stream xUMlUgŠU+'ZEi *:i"Rm֛ew6QOT! zZ~^TTH 8YCz̛fK}D|XU$~uB}NRI/<Ƈ7ޅצר܎{%U:,vsks$Gȭ!|];DbUxfϵt$Y:卵HNIVz-#Cz [Eydʈx0q+G#؅бGU ZT扞ȗsgWs;<ć̫|xHK}/wѴ%Q)o))_)ϕ$+ʊrY||ݧ(u[=vfq1ܱAk3o,mEp gK~nߥvjjyaqmBim ր6vq5y=klfUg=.SfE#fsH޵]:QV݇I!H&ɒf3Ì}sDf7N=ΈY1:yɄsd{}^_{4md(EsߚbPןY"s>aض@ Y'~Gjju72J&"jendstream endobj 607 0 obj << /Filter /FlateDecode /Length1 12920 /Length 8609 >> stream x{ xT9箳d2L&3ɾ@ƐHD!AIH l5`"RԺ5(2(hk+ZEj+*]q03{>ӧsMײ( M9I".iu>s)1u_/^9| uG{K[]bu<%]A.gpz>-Kc~yr=v  o\><Cyahu-H! !܎X[P%_"(󒯿iSl i#~Gz qP}ZUfF==,J O#}P;` Y䀂uܡ8rqoIl[69~!1U Gеu0R\8yX xQ":>p|"xqb!y"g>2X~?8g_ؚ»[! lepQG[?uGpAQPr/;|!C=>ՑkG2Ü0'q[+^p{P*38EXjHUJ'W Rv|T_AyƫZ.6!WHRբJTrQ@?R ˁ#"/r!4'A1D}(10/F>0%(ĚR2$"E& ~<ģGݥRMQe?Ji?=cJ}Cp1K Q{w-)u+tw.WhvW40{Z ;i3x[vм=n/.t;wKGѼ; t+-GZ˖5 #ZVwUF'[F*7YM>>>5*=.bA}ٽ]ΊS`Y AgKcyAcrĝFjJzB\ygy,7S zqB}*h(Rh+z?ix[v A h\U(pE fFt1h uõMx"Wmx;-I%wG>cjJ+"_FOFGA&dGweh o1sٰ2<d>/ |pDI $t9C~,`3O2gd'p{F6D~-~Dh\F-N4 \`΢s5! Pa-\\W- 3\/K|E`#hH=i%KHy0 L*3U"sr5j]g7"nWz Ff.&w_o/X*#ly xX  Ն:QJYL" /[wh3=}ُNY Sls;awBEWOy=$D-j1NQ)r(+ܕΠ9zUUn(; :}-u7jd 6202%$#Yv]v P~ IT78+ nvV+;z+3CNG)A4e5X4ZAx*ZڂӦ7T'\Mu A=ls= fZjdZΥI AӪOUo*6$ʖ`1 .6ZFMw´Ɔ ~d B Π]] Eu րUA4aH5.X2ny˼&p4791SF)Հg9Wz-I{![t_#e.|& r`O 4:c5/,Y*kͽqS0^v~ ں=[[Z[xKD;FJ(wSeUwt=\qS)i(A=(i LBi 1GB~lT9НNYmA9<*АRf\IynuV:;XCG{ocP'F퍍`,:{a3@.5eaPv:(S;azC.^ W“}“G$% OQP{QLo4vJ> BN;F$l(<_D߇ ߋ#BYs#]#$rgEr<&iQ)y?P{Ynzߏv?6fC{@78ŐTxh-@]Kn癠eи?RW2ԝhuonAT/`x,4E!9 Z;?%ăT("]tHc >Yj Q"a1<+V$%f s}SqOpWp#bKYyUQb@I2X_b):Z2A܁Ќ0 yvNƥB;[s b)@M9{V6! kd:dO*4Um1v-3Gj Y?=T[^*-D5jQ>ϛ[#sΚ4=w-B$N'~$_Etym3o)o rPA@)jSu%.@I&Z]CЅbЇ7ӎ-Ш}^&/A-̤eVR,v)> 6]mս.we{# ][%oj@C#oC%~n9V}$|lS؂1^;?ϠxL\l~SygF.r ev!H3 p*# YXE@&o L>6>曗 HB? 'n C8/dYA ;8$$Sw5}'\[s9ٺ xlƭ9Mzu}J  )8'x*AXgv1!p?}LK8.Ee# "'c&xIaee$"y'DMfUOae[w16FHP wۊ)\yNBBya$2t''Pj^@@(pC -GuȢx{r̗%y2a*< (!:&sU]}vˁM˖eMKuc Fƽq~[OsYܩk^ҷV\f|8@q t! qոk M'OBȂ-Pv9ڥzF +ѨgdO"DD VEy#[^*mkJ%EX-*&@4\8c>ۥa\4 ؁&' N73i ϋXϓ%o,i16\*UsE9y.gNxm{YϹ;zdƗO${&wدOQU"9x-P&y[T+eD!$F$gXQ}VVmaǥɲ\%j)T-zRy,9ϺniW(I%RڠsddO\I8Hě=V/PFqbi(`N3`Ӑ̧H΄$QkN#$n%-MNK(ii> jt˥bH?&9/5)Փxd gNw,Ɖ˜v2󿘾k}'ϹRp >}c?GkKk8'<{_^'#=W"msYI^}kcł&h}. xj䒀B5#GQ/(f[Lg]I C"-Q"hIp𖖥Өr2^ ߆eTܩ].|1WX3E HxX9bU"Q1 B̮VڋHX1)Mh'|I&[rgT{D()juB69Wh?gx'F>{cu01] Ε8)c I[< ޅ̉ .dtA-&ąv \Pf4%KU8o1Nx=ѣ x $7LXV-q#wIkN=`P>bSMe&5۔jOƬeNjts쩪iKbG|;P뷿×)tG?b=Qg Ok{$LH4DBV5SHcq8׹N5O/KHYkF^Z9$:YqAT'QRh5z"QNA>TbҪ;rȼ͛wL5#CH]a}t͝sK27ׂwff٣g=o qv`BBIbG4VgUpĵlwgfʕcE( r/R԰JMZ@C c2 ck!y/f1KBeD Tl4! 3eJ+(;|5?[:Jɷڷmlmݹ/y6x B8%fUhE wjjj//zoW#ntrb7)L]گZ ՒXZVv×/[&# X d!^$O@iwaUZD@xPmW[[\ߪpo}ϗ#o}~ $c$N!o'lۀ3 2*z[`e`NI^éH<7}@Ћ~+8ʜǯ0ߗ]tbVלג"Jm'`tmnTxcpX1c,rQ>K|/`Hv*jTŎC%rp0FUz5+=I ^^h/RT^r[]A"ԐHG5󤦥>ZDY.+X@@m 0xZ/'v>~Gp{N^ ;)>a7;iѝO~sM7gNf1eʇb6$&-ji/2ZvUo xCETkRcF}U&n/ f ={wtPlYu΁۹1 y;_tyjS?Šb ec}X-ke|}i1&UgIRXoȵvy|٘Lcff+U ^͒}:TD9 |Ka RPؾS MGu'z( Frx2cOb_Rv67fYL zr4zw%y}y-"RLWy_T|~#e v~)r 'prggnOɖMpO\w=K{~\+2úi_A3#ϝ{OOdHJeԈ&$Xn\uqDΛ "2C1_t{V"'㲛qS`4~XL/%nfCWo,5-ԀQa2ݰ$#6Ӹ6=jSO.Y1sA6kK+g?uǦXreѴM})ϼA9O;f x Ow ^If5XR7+VjEJjÙfYxTJL;",&MK+<-={M?0#ah.))ϺNRJѺ'y'?f>>cH|U|TGr͂ҮUX@|`& amsFd$C(ӫ@si &(qqP^ՐF0$qD40#K&cq D?=ďwx>ju};l>p2s)0Ñpu0&z`*Ľ&":mo7nS$lM'[ҕL]g`ڌ zY/JqFHEEIZ,jR6gy1 @&T8Y4y pG#Ǻv.\۷zf>ٶ}M)%?qw~buC-p5x2XV%J)}"eC\0E 8X1uL-^ l,hygF1qf:A~ {2C- ,.s7 g~X(>eؕʧ${|JפI3}{W*WƭTu<]޾tfՐ` ̔xx')NΦ̯:gNSd 2(˕eufiBWXsTzeZsF7!1]]nQRi #LkKp!|·!B\*ZhKЛ]B$U蓻#CDpBh!1IK,r0sx #HQ8^BnY4"vřyfeϜyWE2XI٦Ys'*S-:{VzŶ^xY7%S "fti\ ⨥k,21J/Ƞ230׍laimEtdH,iZjIa؛Oͻx 9qzDߚY7s"l Wl'綂!'#8mÜU=DEgѧ+wA"N%G|efp2~j~[7*(RXj7G@c%b.f?r~3.?i3Sxny^`& dst0uzn/'"|F*ܣ<*'Vܛ"f{H8~,B©y2Idgrn!rS+i|XjkH:tE5B,K2}eCZa_298ݼEEᢢQ3s: . ce8 p"N;Y|:ͺ&P CZ黤_~kXokfU6h +F.x˰Ӹԏ*40-^:\KNlBRoUT0o|HC#贷c :bQ.ʵd!*°l%ZaL7c\ Y!OO(0އ[˞yOJUf HeG6GRd /ǻd= /08A3A"g|Tt T)}#Y /!kҷuhP# 3`xLJyx㇪jTU/nZ0E!uC|{So`* PPpz]!W ,X0T4t>:硑2FQu~zzzΨQQQQ;G)UoƿuT}zۨ7ި@[`T}ѨQu4nz.nQQeKqGwh+Wendstream endobj 608 0 obj << /Filter /FlateDecode /Length1 10384 /Length 6740 >> stream xZ xTյ^yLf&EBB9$G $ LP#p*Q ׷< ! RZ]j-g{/jds&Đw?3k>k{sWu-  jJ:/&lriײUɼҽlM mIc\܉<qz$cp5j]{ն#>$]w=q} {Za+(v-U۴埂^}_/v\ōR̅a5AՖ9 1h̊4 "6%{QghXNH@bFR1w<IdbF~_NP<*p#/a!s @00T8).FM=BGIi 0L(y$FKO0I_ZSVF/qGwhlp7G D|Fk2+kFڣ=]+Vw[Hчz:mvȊ.;#見Wyύ^*UMGU=bOh{ꖛ޵i]+λ*VKj]zW]b.i+FV/f4FY5W,ZYб! HHq J.I=!(>Lg" 0oTe 3$x ؾv8j|fv3 $Ƽvؐxҡ{ X8'SGc`k^ILdC%c8C;NAr$< O~2L$.'>DQ ^Gȇa{''Dd[[a<,jr;&vJ5>8a*޵p<?7 eut7DQA3pH:ތc:E8Gz#A)(=e\T#Nzש^Iga/o__2,cdTf<̬bv὇3/$v;e7ӋW7f3ř8;PfŐtIi8ϒ6CZBD #BRy( g]6 [x%e%v {Jpy(E÷ gtϋ&tmVd4u)jR!jM7l2AmmaAۨVTeo6Q\VRĖKǴ-őD-lo*7Fi#UfotPNGt }>|[mFI:ZWZMN2'[2"0mX":UQXGۖD4UW9}f,â&|GN( <UJ-lmQUKֻ?}~xTe ԴuDև\)*܌F/vKmlnLH<@N%vkBu7W;V"B}S]˙e>9g[dgضhH!Qb%~dD :Joq W3a.G~D):eڢ7J2׺_awȋPe3oM:S\[m >RYi ;mNi~{9żV=4Q.M Л̞E}B67Hbc 'Go[ْ-c&' 2}d{k5x}Ӗyk(LL@9llB`.Qlv$;'`?R?6kV \;q1MsUΨXՌ{)z%[p[nyd/b}}RM~_l_Oҷd>F`l8\y}Ny|~,a:ED.|C~'|-F8 rLBxI7!\GF&'#p7𔯃pBzӛA% i#|#323!³³G8 zy 7!;72y r;WFx7pByӛ^<7K:h;;7n=%T)nf*{K\)3wARR R-0\  ʐzM1bq.1{aM\ዽGIwwGj< 7♖sF0N"ƽr /5Kح[~HME%s4U$Ϯ\t0] 24n $4.'e^X >}SbLݗx(n/בI¤W-VCq<3'ELlܷ 6feͺV7x1ꎪAEE~xNZ C"b#s)ضvkMĢj);ž_?_Y}go#*NJXT z0f(p#K n2L$N^|oFb. S5uD@Pj)H BH hvMI&f>)k  dz<<ųR'b@aPބ,u_K`|t(OOVSaB]=̡}//R$w >`PT'/w7_t_NVY~3 ARHkHbC K.IRVx~ZpB*pIMspQ.ʐO;Rm*;-ߊ C`(Eqa(GJ6h P !`Jaʪ6#],=t$t u >0zG3Om{>=~ܡJωY~OIo$59S`ϡ%M.1zE T ze[2EHv+WrPH}>`$%f$FEj0L0ӓ qfRs֋읻n='SϱX7'>Gu]=c.a]t <&2)rsF)ȵRI|<Ӟl#UO`2Uh5ꔀ;-HBpj\phҌ&HҜB\9_Z0TS,Ml)ӥ٠%;P.*,StO)}Y ;׽'I v&s0S^wvX*:fωHٳË7P9M(!f)cEJ m.(|#bWQ"'9*z b2|=cTFx VUBhjTTj@pJ|n;sQLG!wGEN=#)6xmh3kyEEy k0@Oi BN~7PsTuxpx=ǻwm+XW{9d׽G6O(܎ۊR '3P a T:J+!ACRpπ`jTR#92tyi)i{dYkM/:*'wS:zh7c \WrID~b'iyg&j|Sӧ-M_\^VNt6Ҹ̳9L겙sL j @Z2~ryٕC/Yl!뤌 pk 4ٸo`316`d64MRH0PƇ`w݂qhmnq%WrKݗ>O(xɘPp!ڷd]4')68鉥˫3f}\OyZ^]ZvhΉSg5v;7_~o(K']֡)Y 1XJ4Qh_05f-)w跬~KduCWUDV$&X$.<4秤> /ExtGState << >> /Font << /F2 541 0 R >> /ProcSet [ /PDF /Text ] >> /Subtype /Form /Type /XObject /Length 509 >> stream xn0EYڋ2r6F@EIHilmHL` څd_yAXٕ+v;&nݲK韯~JA8''V>=Ow)ɪ^[xh@`U_DRPd_gܙ.r[?M&2_ie9~p0|f7"*N vY> .E\feR.KQfqywMU3sȅ\</o`D˕^<+%qSz^%SUZeӽJ'qAl7 E`.LkuQf.}xE(3WhQ܏X?c;ݝrkQ/Rop35;8ffO=}tF U*蠍HewIT)ViΰO?C?vmmkU>]2-s=swgq"s( `rendstream endobj 610 0 obj << /Filter /FlateDecode /Length 2401 >> stream xڽY[~0 F$u-6\ۭ6y-dd{l7EP(<<|;O^-gM67I\%/7̋+͗w?-]&!IRXޙM^yhC/Y8z{eO% ;( !&4vt^z~hR倁 7_gg\EФ!'WѡUq,p-˨.u6?R6y5?tT**HApʖZҚ9F@ިbxMW@EZ"0S'gTGNE`tol-(-`7;‘z^'HX H}/"E6i"1b\蹴| D,diN"ʂu5ԫa2ʟt2@w?-Oj,ͦGeK8D0L"sаO4aӡL!ȳZ~o;lU@"Px$ߨߊp+* KдW{Ai[@ ?2E7& CR۫C8An\Y"GPQ!%_P4P5v C#o4f0QQsQR@m'I*orՁtn/4JB!H.KLOk&:IF؊)usUa%Ed^I,CH$1q:\5۴*q| oOeˆN^i twVSDIHd"['`ي0(t]fF7h.X# WU8BڳN4~ss 4}#Ud^U}"aUDClː`aSN>uټεT28{[̨*]li$e"j®JM}(t/q󇎯(Rpq2Xƿ n0lإDe`RjfN/1u)a9w[쪊SmJs:'EF(0*4 _O[iQ{~YtH1 `q4ϧ*6b]{\Pqx}u%z˯sWz% t[ӬJ.(cQ.䷒ȼá]艺^{ EBCu//)C$ (@Z_wa"1ֹ. ow/VڨΏeT/"YO-nHWH傛_ Wj$_!bΓyXw2rF?ēˊ.ea3xe6ޞk!yLRXGNK ި5Aзp.*">Oͨ2yOPFcD;{ȑ`\3jP]CA8:Kx?:zQendstream endobj 611 0 obj << /Alternate /DeviceRGB /Filter /FlateDecode /N 3 /Length 2596 >> stream xwTSϽ7PkhRH H.*1 J"6DTpDQ2(C"QDqpId߼y͛~kg}ֺLX Xňg` lpBF|،l *?Y"1P\8=W%Oɘ4M0J"Y2Vs,[|e92<se'9`2&ctI@o|N6(.sSdl-c(2-yH_/XZ.$&\SM07#1ؙYrfYym";8980m-m(]v^DW~ emi]P`/u}q|^R,g+\Kk)/C_|Rax8t1C^7nfzDp 柇u$/ED˦L L[B@ٹЖX!@~(* {d+} G͋љς}WL$cGD2QZ4 E@@A(q`1D `'u46ptc48.`R0) @Rt CXCP%CBH@Rf[(t CQhz#0 Zl`O828.p|O×X ?:0FBx$ !i@ڐH[EE1PL ⢖V6QP>U(j MFkt,:.FW8c1L&ӎ9ƌaX: rbl1 {{{;}#tp8_\8"Ey.,X%%Gщ1-9ҀKl.oo/O$&'=JvMޞxǥ{=Vs\x ‰N柜>ucKz=s/ol|ϝ?y ^d]ps~:;/;]7|WpQoH!ɻVsnYs}ҽ~4] =>=:`;cܱ'?e~!ańD#G&}'/?^xI֓?+\wx20;5\ӯ_etWf^Qs-mw3+?~O~endstream endobj 612 0 obj << /Filter /FlateDecode /Length 3622 >> stream xkP(Tk.4b`_NQ(ND^Dw^ :;ͧrwvwvvxq>yq7EбZ/7 ]e*ENz!RG[>.WiD^ÿnnwQ~W}{ykI=p{>.UƓ;\ Lf2.uo4-Uk8KzQ,ӋU(}^LgY"GđdI~tB֎4%i4u͓ 7En^ؼW:tN\qi.$#S i T+]fʰm8g{|\fa'@$WJ+< ~&*3 MD}z pǑ5?^0Ȉiq;Yh䧽~끳f0v2ϱf:Yf "*̺$_$ݩE4URm#l_Hgoq/ p~*Y9t_NJ%Ι{"M*33pZ!DddHO*_5;?h'Uy"e ʅY3o/k4)t=" Ԍu6B7vM<8:,x=JiLqe-g}>EQ؏UH"htNe|OJQfRXז|ZgD/ )cvSUTt$ɫ(1lՈXK ixy(wΣ=lL`nRT~y,3v K: R) ڍ5q5h ur>VPzk Kn FBW˝Lk89@FILZ4@[N= ҈It=zxT/w['3 r+ :Fi08H ACb:XKǡՅK@ !3w+V+yz`=sXwNspaT&R>D#2TFUVaSd\ɓ5I+{~ܚ73P XhUj:FCx -ބ+58sC6w1F9Tź:r+TqU'eXFv̓[7(ED%&u$ț:MYReR~bE2.9ė&Y+1Lb!8,S-k/iif1MU Eb/IF/$QIl'i-4AV"A6Ouf=fmԔh+c_~T:799xdcӞߍ^sdᅼhrIaPmkgI+*)pY`;HiF,ĥ`!fnp6qtx!+qA%+{ >1GIII1۹7&I߰}ufs0{c ;v_^$+,+]%*N+p\ML~FE?CB~k Iҏsu4ᔾˌ- 4xӃ0&lɧB<`,,#rbE;hmBrCa0CN/d-ف} GЬ~n,'.$wd\Eop$" 2 SAHy]a}S%Xx޲Oܢ3檱^qxf&?G/@.NcicD_GIc#qtʂ%1wFUKuIuNo;r]ÕԔC|47*sHI[+*0?q NVOb=O<ӓ]{:Rݓ7\fM2 ܨ+or֏GMD@3ex@ی +RuVR*l_11M){[&*F'_Pm7ِA9N\0H7RNU~ QX$NjBߌ 6Eꍗm'|ȣ`< 0;z\X)`IO{ԓҽ.q*_ʯ#wtVPi<%>%HL]_b14S _qLKy~(Ӌ0ȡg%-[џ9g(o{꽸ç#+o)\deyP ef">ZJ'c=9'^FXMS7ֹ+px8:Oυh:T,Z?ὡ;nBJЇ(᤮ { 4> stream xڭk۸{~$E^Kpk6ԇůuϯZvHIA9$Ùd=Zo/nߙ|dumF22/U|n1Jdz+T;@B>ܘq'yy{72X'r~Gxlχ!z ^9j|jWz+U3Ka9 eDx%xK]~DE%d*w5֠3ҵ` [ܴSjSDp̹`װ |lHK:+:y}/o:xjel璦4~;"p<VpGAT̢$cAz.x[$9#iR* VxY'6\SZ4. @ fbR{Ď?CylanOk'>ar`hZ+sR?Q S= nFsa )HzI} eo*2-`Qwlz1*V=tpb?"k|~UWE-}XLi N>'>xʐx,ʓ\櫃HDX\ 6.>o ? R{4{)TN>߀udcפW{(2F|ILi>9]ocA~\z߫FwfsmOa}*t 42ztoup+}kww5Մq]y\inChj_u/\3 Õzq6`M9 Qu/}U .Uw|B喃FalvJGё|hŸq#ke׃H/ Pendstream endobj 614 0 obj << /Filter /FlateDecode /Length 3687 >> stream xڝZ6¸/'bԫ8I"^ 4lkwm'Io$n"pp8 nf'ϯ\ʳYUTų,.MjVdEX캙|>-"M%kw~;ɏz2gzvL7/ J8 |aիxyaŰ19I$[ijEe0,I50CҫBsͳP ʮ G/"QtE {b0S]7<~!VO; k?_/u>,Obv:mE~HWbN7U}hdɹ=805:!ɉG,Z/BYjyܿ$AIӸ go纗 ab$!Qch4G: #sa?+sDŽ5w6OG& XmYmYEΪ(* SCaJBY'Yf^TNćA7֣ Yx8AmW$zҬ(wv5Ӱ/m WUE+q۪&v#/Q aDzϥ:\T$t'ڽS P,2-۱jt%4/$ oTv^4l8Ȥ$T1QȼFIP@5ekUiz032Q5qoq <y676w@#^6>@AypE'~Xu;~L!.NiIma{ew^$l︷ar$ZGM- dkZ|N2'׋.,6]J"8/XPd?MIU70[-9A nDkKlK-GLn`7ҭU!9IQ}A;Ү1V xpQ|&1aU ʼnvs)Ha:=hAJۉN܏bʒNhWDsH7ΤtR9zI&PR=eJzȢ$>A-)4iVP;.e_j; =ա54Rvb̆U̿k0 _J1Av @mt۾5iL%q2-"lD>DY@oc;Vz-2o-n̝sѫQYē:/I|[p#Wv!8N{O(eحne`WIm(4p4~0ɪGS80BԒ|c{]tN/f=^?qOf?;P4Qx[f;AUtЬHN~! ;w @ZT t]H ;}{(jؠhA<urĽZl΅©ͤ`=i$ #/6߀ UEmDK-NƉxxu)R\ "K*ij3;{S/l?=wܿsI%½Qb|=:)$}2BՍSpYa2*; ƃ\LnhɺnH8ܞ$Z|Qb_gxYa<eoU{E%^k_\jk*~oINMY"4థ^]ˁ̦V1?6qg5`D5A']7rhZU&l؋n (yX cy/](ܢ3/YE&׸ 0_ဦq}-GL/SEoeԍMª(IV9o5&/绲^č{|dRWjz44#0͖&2So!rJ^FrYze(,7K>}Xe=*֜.2kp4E3xo .HLr>9x U Nޛޢe_ꗄb$~“&#T,I5C1IFUQ|>6ͥrm4%5e[ORh]v8s>NdZ&UJ@N'*M<w>@qn w2|S/]C,B>a2'c{g% )H&9YJ} -JGթ=g~1Ocp c%a[P~o(Kf(K "!^_y_3& !5~AXg j:V%}{i#ԤKƹz3{,!q)r^g%t 'am qXS)tQTXdzP`=|bA?;X3; +?ޔJ Z+c+\5^lW>VҾ>t>4*EKoV=({Ӌ",L9c/NpUlendstream endobj 615 0 obj << /Filter /FlateDecode /Length 117 >> stream x31ӳP0P02U06P06W05WH1*24͡Rɹ\N\ \@q.}O_T.}gB4PS,{h 0T0pzrr۵&endstream endobj 616 0 obj << /Filter /FlateDecode /Length1 1579 /Length2 9995 /Length3 0 /Length 11034 >> stream xڍT]6 HwHIww7Hw 0PЩt7HJ4]J}kֺk>>4٤! y3S &m aFA@P70Y?,d ž ewG_K@)/CT [g:  =h` 5  ІXA0 (jspxzz!P[q&V'f k-ԁN[cG؁RhCl`@( 8@n. (9;@[I_b'; 8ζ#F^c0:A@#ҁy)Mÿs]`nn`?z#圭e NN gɂ {s}OgI6`gk?ڰvwudyق`>NNN~A# O%s.s    T[ [3? Ɯpd0kb#=Y)C[G)- ظ8\\?|m }ӿJ/cC 0&|Vg?_ɻ;:g:xf;y ϻVWh:%ym#Mì_vi@<-6.N=o?UrV?P(%>/:Zd1{v<7@Q~>ПoIaoIa?C [^J%t.n1^HS?4ա6'jݛkoώHPQHn=ux߮L.Op٭US0azKs_l-Z7mO<ˬ)Rd%*3ϋI'jxthB_U) nt/H)_\3J(Ed ϿNR{IA }_&N@בi uԳU0E /QI(1Ϣ*WN["trEӼ68|E1#=vT&y{ҊT0`Ow 4vS8['U̽@6)݌X?8͛Zx۟0ES `T kvڭiew{T3}qբy wP~My@2R PwmU8픇Q#ɲ1Q-mY۾<Ȣ캲}Qn,9￶;G3>`/nj o6`y5$8u:W[1vj.dQĨKU6e읫h B1eZ¾_8Zq ,ܻ$ȋ>I5et$oIYa`)PMbZ96Ph(~~E51+eAmh:fh7SCiDfUŜ  LxP*F2;葺Xr2-k<9Hv u9W7oe*d\iiuk3s@v^7H{| NEd(iŪ΃'g![Ы;Rc;0{ T%u۬kF_%o57 O]bV"'K\30fb3PDEY& lX5:\FJN+Zϩaa _@')$[w,CۖYU:R|l%2US;CxT]ڌ;BltE^>FFdDop6>ٶ%6uR.egbi&Kp~1+`n5R㱰s}hzm-NK]9Lr1&~}.HRtPĩI۽Qe '\sA^uqٜ ཐFAcǘLrWulyǹXWwٛsͳy0LDUx tagKe[nX>=YЋ2u-Ze _q5k0 QW}HT5OHT56~ytEۇjgHipmAxn 3M8w#S#ݩ 89xd YDVA/h 0R#~FzB} 5 lwcciHC$LQ wF>}:o{=`KϮܡ݃We h_Ey$K$) ol6H}?c*w>X0\ 3X,` q:2zq@G+\r!zi61Ll g=rI}W*Qmf}LUc\Hc'W_yI5bg tq9[ $qݤНn+ Ҟ&qnrO+g1>h aՊb{92%/F>{ m.*_Bmdʺ8E b,va0(-Ay3F"!P8!@60\On a̓ww&ÚX6Ŗ8gaIE='rNs+,q >U>ewsS-p"'ei+IȂmw>ӎ?hj *yKNc98+TUᗢx_N.PBN{qK7wTqu~-?v8-`*Y!hnl!W#;bR|F=|wfB6Vcb]2Nt4öm&]wK,v졄$xXzNeD.۪?J%֞L\qڵT=JN]TsDA"i£d%q 'ngU[ vHnu4|o }G /$>rJg ]U}C;CT8p yZI]bxnZ5ʆW뒻$fܠi Փ \ˇhȝumpKp}c}A';ؓ$:y؍H?ڵi*=d30m)WB WF mS*VW[}qYc{MX64m!p55yn&Lԍ.,PKsKtkZ·YNtfpBFE0%@OLIVf7W/S:|C=#˶}Ԇdv GaBA>g 5iD/-ꎯ'RN~Nf_mjaz}q1Z)8b,T(vÆ"yM/ U fN$ O$ 5K)07I7D%w72Ū/%ltJr]ūRv`矶5E@W݆U5(1թ18y{ՙ%_ZKHuQ [Xq#"0TJfH:.` =T ^/|20EPDbt\.Ma([ hS 3Rw]+4n U ~uiשx.?_HӚi=jBr|-$ɴE\XVJ!VĢU!1f >}KD4Ӻ{z= AIooMAQl9pʫnc ֑sbPR/[qjw8Ư1[촗T6fn“-Nɫ}|,.S?1k+ m_ ^ p6?y:cSϋ4%$nU2$lc]?"2uXu/ii7  8~M?'#?X/ 5C=IJEoYÛR\O3뽉R f>5G57 gS4eQK@ͳ1O)/]>;M֫9zJE`;W, ܋^?,)!Tm' #ݵ0H1M)eTMLWgke鿾^Bd-tʔeb+h&)5k>$z~lyJTs5(y Dzj;\G?$Bi\;XNV1o|<^ΝU CR~ө=hy TUĮ:ㅩV)[ף*+Lt~IFwLFxdPY+?NmS`9u.Gs$DwDFy?I5x:m7Q-Ν<_VԬ&rB֔gs'/y7dߖy sVd40l3b\DWZZ'"ˊsohYuIēueMmc^1Q<_sCMsu6`'5Ȉ%~q\B@9Uyo,8XǬ" "tf}:nD@j7s.ӑК50Âb1:ūepw%eV+~;E@[f#8<`8m ϋ;.wUPmAezh,,na!@r8YY٫NZZsM/Y؏07ya꒢o_WQ!qJd S4Gf9Ŗq*:8dmȷ<4UZK  ]9H/iK N̓_ Q?gel+27!MmINE|@nVLl42&$o`߮sz< {$oXk \겮W3P(-|2+oa"4]!vNj}M*aVߋ1` %/v5Gn;g&+W:}O,֚Q2z]8Da<;v= oMu44r&0ф!ݴjJC>E0> oxvGVߙVN"h02t;1|鉫~DN'0w]7B&ivd?6PKF"(Gx6ZH'0sB(:? WbjQqT7 mIsYiO"<Ⱦ3ɔ:,}gڗLzJt+(阘g긴#.K^ .3կR_X|X杕ǫ>:9^J= Y oƸCoowU/ai6Xl22mYx٦vV"R}вՇwbJIqqo3aP4_sc+ލxc{Vum)n^Mf܇fMh~,9#/e$jLLe!7M2¿›*3g.\`)fuEGv-/|I @]s|TI:;fm2^7 'DW/SF'LM}CHgy7cPCZANz(XdzEsCz[dWiYl͚a ]"1iF*"bI&UfI!{qZgAnêEk_i omhv[FqZ#P#fOw-D=D~~SE¤[RS qafi(,浂W0QdH_"L1]*L$G>$;LuS$|Ǻ P=8 tcȶˆd0Ui&13ʵ0_5$AiӵK+>pJUXjAMZ\c(7\{Q X~^8>ё׫U>orDJGs]ˡFtkWFu"8p'2tNk״`84&DE;fx~l뜑iPogaLǧ 7BȍAjI݅ǻZJ)`S<ҋyE᱌E)L@S!=#oR՟{Cd+ _t9£)y~sM4uïH| À4{&)=OXEYh)hAzu'Id4IԲ- Wk#aFbr1#lp4S]Q u}8d赲+k&9@-6WQ"9a[ oX̿÷#ݎƕ0QL|5'AJFIO+GBrdeXi5r>4]ԯ:hg^× %E4+|nh8{I @^ȍAv䧀H@ f hErGڴgàlNI0ղHo.GbPn8_dc6;ock*nB\!T]s~$\^}0;}JRew!jZEE?2J' }"M{, G@ »7[L$^6V:O0"gJ_lh[\dkTpWҘ0rs4.uƳiM"dgL'cɜEFtI^ZƏĞNʳ㩃T%$$ߣ8IPǨң䃵/jOKoan"LV\P[EBjpa#{9H!jH?}ȷ&-%DŽ"`4nl*]Z:BC >Q9Ie`i~6V-r^Y k/DoE~S0 pb}LmlrWD_K̺tbاZb >n 9icib;+6v3%%|&sw1i%fc"^BS,PbI3J(5h$"i20yD{۔oX\D r$%e%)wMh>=͐ Gq\Χ2:^4ҳd2;<$՞'Z4 AX1rݝylqdd| |]+.͒#BMCz?ŦMk< QMg$!OTQ.v3є?N1 x 0fKK#n`BƩ*1f.0.@0іHmLW~`!${1x\<Х4.ȵ&P7ᾪ.tXg.f9f09j9LGvAJ|V+on.-Om5$/ڔW}JmLD8 Ep!y;w_ 'r;XO$mu$Fށ˸5c~n銰IPo&nӔ.R P<ÓpxJ@elk'K_Lk˽Wʟ|EH?b= |7.7ύ)yFIQDtX|좄fǐC!ǯ 9 yh|M\QyM üC[G-+r낾7*" dO&Nqʩ)&m:6N ^"*W?JK@"in+YxQp:,Zendstream endobj 617 0 obj << /Filter /FlateDecode /Length1 1411 /Length2 6115 /Length3 0 /Length 7074 >> stream xڍt4ֶ.j>{ c Fa:zDDt{AQDDO=5k=v6f=C^y{TGEme3?_/@fCB@0\?H(ucSn8@D$@~~@ h8ԓM9:n p@<nP$ ('MF`(rB%|||`7O (PO(j2@ ` 0D8|H( @7.^p{(p`u"kEW?޿࿝ 0W(@WE Ep_D' nKT AQ@O~fe" GyO Bnݏp]8 n {/w>c8 sc" /ĉW#?wo|C pis=P  D'!AP;# N7f_#aK~zQ=oY詚(qi_ @BBQQ@?a gu W7wDgC8.o[ Cnd+H7n0W?zn@q B]m=QufᎮH jCAR_v_ C__/|A\3i<& M,A[, $M/T xvߧc>x?A;.-Y,`NrpV<5 Ex=c%-U  a&[EG>y;wO*5aG=27BzW E[T -{K"&H<)VX#Ѐ\y%Nˇb%.3/ooI^Fp|0_a|OŭTi*_һ4Qϸǰ?+Yf!+^ĿN#/POZ[r!#6sNS>.+젊/>O+>OD_Qwc`i!pIQ+&,Y"]Wr} [25'#(q1 DS?"]zl/g'E߫^E[/"r1|G. ,/Cj7u<]-eH\↻@Z_a1l2O+22w6o{;w]yadTЪqs';i ^)U$Fv]'w!$^j.V~_ b2YaƇS~LÒ %HYD8z_kޕUdtt$V7%dZ 8dÌI̾87M%e=cbuUԩig]~cXÐ;K_>]aqN:c-{oA!vPU}J|g'R =nv;rcM`Hߡ:Am:8{yQ'˕9Χj[^1r(;俰Ο'B)N Tu|V--`:sX=W;)8>thХ*6 $\pR:؜y {z29wRЌ!ph;]lMs-gW3K8~`pd4߶ɾaMKw) {9zk&.zP`#@[s!%f*xSs0nߢTV\@b?ގ'qQ&s5x+vDB4a'k:9 m仚JnKo\;oyI+#Me >L/[kk2w pxn9H *jUYؑqlxvX FĤ/μ.)F$7D"CŃmdp~W. TyU ҾQݦjG/`A/(/+|uCLb"aQZtӣ'T0/X$f@W=_sn[<#+ּJg 9J3Y}eF*Fտ?yl2_Dˏ N\2 b[[U̼yN{gUFk*O#;b;%hȵwI 8(^|nCJl ּXqb3o8&a3Il4%T,A p202Nbz cwX^cN;L0T? eqHZ7-)a0 "Vir0m: !;<n0 S@Hʔ9jBbO{)Rs[/C ܿt7O=suӯ1H%}v ܓ O O>#iXplZiꄄuk<9nlo%j fR\IT2 a=E/Jez|rZ鿇60Ym"0c)%0n)aڬ6W=XcD"ӊ|-$ޏck۶9H8yMKsN#-ԲI"');#nߎyVӣ*G7L$TL&1R՚ΏڵQ8Ћ ћ$Ri[Itke9[#f# "?sls&xF*sXwP 8mh?`h%*ʱy7W/NL`X d<`!eJUvu q搤WKC3\0;||(?_ֲg5uV(d^lg|iz'6Um8_E?>5Nj> vʇͅrP|%q{S\qQ;sz$D7MەOE)%M!̦#'e]wZ -- Fo)܆ʁ tqD܊<5!!tA?~TMݢh H7ND^9͵ ~U!GVڵO -g;VX ԌNa9ȦE){}a_ %OXd{ mmji^Z1F}q g'ma(|uiN_W`/bl`fdc.ck/0=2SmÂ,󐦜Jl2VXgF? DGq~ϻ1n /QZI]M'HTAWp^ِd.*#je2݆8KK(ylj>_J}%u3=$%h'_Ѳk ^G@֮p|˧c%q*bж H>YIL&>J8}z'#eC^'<ǚ|/*U_0YFjH褁<'eG||ҔꚄs;.'3Pc%'+ q`!2@'d>v0n^fU If?`shh" :{G;ōߛzVyWtDs=>nrKcH\sNo07u;XgKiuR (ڗWX.]TTUEm8AFk;%Vʃ6'6ov 1UIC~o*%&xLw2NwT?f=/V6mURe) #*j%/r#*MӂsOqC:YY+z{j ꊓt'`*qb3jb>;v!,j4o= Gw+|fE+Try.:-4~m U&f: '`ILew\Xٝ5o,[mX3/ؾ]=m0HoK=CXByTFLO3bVҖ$g\}J%4> ;Ut2+W q{]%r0xR΍ yS3Wݭd*nts aWCfzM{@nv?WK5aEn*6j}&PH>1bjGR%4q4iJ&/`g9Nzd: &Uy!YSȿdϨI"*%Wk3qH$֧`ž%ϊ/mzSF}g+9^;x}KINڕݹ Ad)ͽf GH??H6W;X|wal uLýDy%<[=oj9~Adm/*?tS:1O?=~&Kf R> stream xڍwT6ҤD$4W 5$!PwޛRދ4 RR( _xZ߷Vg3{?ϻްy+g*#^P@A> Pq'c70\? (()18P @"⠇@ @@n0[@HO%=|; E `8@ qv G NI )vA!P\0@ܠ_#.? `;;0ƥ#W n*_AݳpQŴ8Bf9P}|*+#'ο8 NZ 5]--G0`8JBahe q6  >Ba1, b8Ap4h0/ ʼn}(!_Q('q0 -7|pC~]4HclyB\ۿz@!dDcuPq;ʐ$v걉P% [ij1^?+sJdHұ][8{Ӟr k!/=Mᕱ#xύYċPx#);Hel)Ww~Np)V~ܢQYI$fɦ`Ex~gKQ)w5$N+(zfD찅`$VͼqS䶙NerSvӶd+Z{aywgbCD(7 3rF>a;J+p6L+959pD#ECOxo>unv!+xh36|_9gr :HΈ5P ^w{ +tbMcʵ"M]N~ W IR,zWx,Zh |ʰ-.>QD!/7#M/uk疜ӾA GnbnɐXWnIۋ&Ǘ|pC9EO]E8SO~ϫm2b0eY ޛӜ1htE-7DrV1}R,O'k澠=#^ V6+KKխy&ӞwY/ge]#+u⸂ٷmvܣ_J(Lgu&h^[r|\h_|d֔ m]d덻i6Č蘸Sm؞f~C > ޑ KlŠYk[hgVpc㒌a| b\1i!1hϞ9>O4䉗6nQϜ yFP|3G"22K <>֜Z(qL9#_^R:.cMf9YwfmI 3(tFs{fBU ju'|ynik (ZiH#Xq(N*lî^rQ>yK=~dCiteuMee^64w8Nz6]YNBeB'i53r#I9 J W^7d R@ڬ8Ts(qF8>=)FE|Omi/J5bCb<8 p(.ډ?Bڻ⓺ϤUF_|26>tVscݡV700c |j\g2#C UFlv9GCʸ!H._ _wXel"[ag~ |Ov" ̤d>U56IN U[)yu\2Fk,'<}N\3Z̠]ju';5Y3;z)|-jZQ./)\_p>EϒIń=c>{j@g/=$DHJCZ{I0|$W[[|U_p=~}J:Uχk+??93R]d;Ӡ1?x> aV7Y]9Ӵ3ͣz!D{ED0evԈ? ?4#gx (r& s&2a3ѯ> B_lrʇ#$`S2{KPblk3T9[+rM|دO~*#C'"@ ?Y~wzsgP||O^*M=Ng5X]"ge~x~ u>qN=U Iz4A .eSz5{._3pf{8&'joHuY8|rhڌˢ-o{\ŅPl?rXR1ixx;AomXBT>% \'{j@u#MTBTtۀw_kfm̷cv C^N4"C_RrNZh- 9/IrSi+Oe|8G ;aD."[U8dnn.3Z'e-ɊEIEj& R,0(J* 3' ^|m^hh?oHl.*Y S\{{0oPjU)N9o[rUS ɬ*] ]z48[3&Qq uuZrCX5'6;jg'Q*D$y+r\!E4?snPfkzҞݒK *hԜә9цUabxE/@ypks{m5zQ(I/󙟁7F2$)aAn{#_KV)KU ƌ <9)٧(~ `S祮Duֹ(#9CўnD,7}RS,\goPB/. .!6hއg #{% QIH%6aZ%5yBNgizxzλD.=X.Ra){$͊9>|H&ZkK!⮄=}9};wKIǨnVlul՞-;;c`_G B2J~Gn,:ݛُ=V'W5'd$y8f((7m3+N|闹uTo Դ=#Ei+HY0augX#9IiBC"!u=PeS(C}#-`I]aj$X/mm{P}/,i0U0m:,\W(0:9yRDS?ZvK]&PI[ {nNiI@*M!gEtHB姖Dee(Ƌc2TLlb\hu/&|Ef@Q =V^>,]>9YUO_F;0 I{<U?XJӁ:~MWjƅSlMЧɪ1UNȇ+z#,Rna*h|*M\0.F󜥚K/\(9@>J?Z3qh5zF*'ڜ,5Fʹ#;j0e),3;B%., |狀U0z9._L|<՛II_k@Hϼdj>}Cca{# =IoEYoճVw6:5ez}iM+卉b|IRw+kߣ%J{A#GYY)wNלP=" fJjlK (&st|&)?~'_ҷVjO[$iS@DbF*1:!L#;B|:l_~4؋jXmkO Ɓ;0^b] B/Ѯm"]qcӈ8:M[P|eͷE޷'\/'1Zӳa>BD5IG\_J%Չ'+yk.SZ1'nNMq!M6Pq9l޵rW/S{t[pCv7ֺ&L_5nU[`a@h\--)T!>F=+ԊIjtL {(wݳ1M? (ּWCLu1cr >zf0^-_-4f*G"AߒE{?ϓ+Hp2 Xdw/h="B~|%l* ;ճXO!!2"r %E֧)|ޫ%PWkMA5lA.yaިYE}2+mgs,kvʻ=vN(%hR/VG7ugׇq񨐘&ZtO~y>.xho(ʛRrSAXg|(h09#;孷>8ę+fj}? J> stream xڍTuXTݷ$t$DzDRjnaSDAn開~~qA! x 1y2D_"Q_z-^_?Wo yEy ߵ7WPwz~꺙ASHxCuPI 'ʠNʉ1`Mt¨B^fƴZTXҡYS$}r c7ux1I=K$YBT'6}8i-iN='lU5Z*_gߥ5~gݭ"xp-{9:p)<,Y3IMYA:={5_#`sx7Al.EvVZіMgɔ \/-tݚVܘvŶs\dRq=?!cۙ6u>ۍZqY>ԇN q6W.{C3;}F=6kWGDRM5}/?uTMEڹY9!Qsl7Yg#y9NjU 7fpZEh|{tR0՝`H3~zpق`#MGNYX)ГGPdw`+F |ܣN|QAsjҍ5h.C Tkz>NhojG`;4XXI7p+ xz`(b򍦍40c'6OO_Ah+ZWj}!?boeYʱu`De¯a'Kُ]Re t.AeRJ9WMyfݔ"15'V2yAWgE8eP+S*¾W.?Dog*#} %\R lh AS en.W&PxL1a'e$(mQrb&dXt46b!̺.Q)39&t]҅rq\[' t[.]30[b<+!54U*v]}B!^%ভa+ 5ZU LJNePyeFpZ 4CD|+T;HިJ9AuvyV/KH-3pH qQ6N܅lA 8ݶ^sXqWi>ے>f -ۻ39fcwS_@;桻OwLV= av4ޮMd[En(; |OyU~BgŝXe;xOկekga k]1J«oV(I6ɟr>}l*Z4d0H )$Tg&V#w znzGX֖rYμ. #kŨ!i񽼹7ql0ؔmj5^!To]E”F#l(VGm6M-nUlИ /v*K>C1ٵHskWݛd+&XtbGOib|ؒi|J%2.E*r mB0=+. ]R?HOxyoo=9SI9)?] >,qZnUE ގ@xi MNTT,ȃ$2qSyy)Mg" |jtcd)s^ =HRǐg  Nہ)]{Ss,'ϼ=͞DMG{|xڳN/uWZ 'E|܍0|\I2= K2Mm Um 9wHc0Ǭ^x{Ӹ,8LG9mg;T=s"1_6ڬWuYNᴟL-ayXF߆;RRp0r63 ZЈ-҇fw\h>72Twd}w̏{7j4+:o%87\( {Pdwi߆x&C >4Iã;7'wJzݳS.EE7 4@6K dSs"sm:N#|RC:{kU1 SĿ|`y9?jDGA^16LHs%aoՔelor:z- %0/%x6gĻwpa&cR{:cFzc4eyz+{?hk8_U0Xyˬ ŕ=/%טEJ81%h*TFq>쮢#n[bҵ9DD~zT,c5ieӨ*Wln98Hєe~Vf^Dx1J,4Hh]7DKv܆w  XLUC皻>߉\R2KZQ|6< O?GedNѬV/>%4;R2?RUqSw?ȧ(VWVpXaG^/+;P.m]^ Uҁ)ih}r(}"؛dP`y+|Id!:fTu9&NٿkͦJw9h٠;9,n<>Vm_# cE R@y_dSHV^thebQ\!.T$)X+Ou^⮩v:Dٹ&7wM=/6c^&Wq nA}zo1'Zm!R۸"laS.h??Qz\Iƻ[2dQ[=Mzq>GX9lnNUB-R!$@ⳏꭨtδ|‚9Ӎ%Gk2̗.vkINV2~5 ~JuESTV=c/9LN]Su #!ŌOFmh >5 ]|k?)Ï%V jO(*>Sז1:_lSK1GF{yh|H ~Do|ɕ.٢Lf=s(§u@FY5Br)6j[jN4pG@>?"mnO])U!Oly^w:۹?yf=:bVo~R~XQ铿L`5jS<|O]eMvgӢJ;ϕ! +OxTSƊn^,G E6I1crB\BdGYT :?7I%u,n\40rk]?|tFgR!sq}hy,3TDSy1%#ZΒBZ/}3}9UTRdO8\w4-q 0C@Ŵ61!i|Q6n3*3T}?ȹ2MR#Z ]g:Yf?ԯ@)ǫRpeHŐuRrLZvmũ9[9QڼLj{*Wc=zj5lQ)؊<86 zHT}bY$(OWfSڋ ԫZ>lmaX$'r$xd^m]dV˞yx.c>(@{%>asԵw׬u5{y0S~8; LbdX`a53kW!($m}'v^cl6۝R/*P]׋t3=4GI/:Tm'bmDt=C/v"B凭k{7DogƏw>J$z{BNW+,j̕QYԵL5{7헝Tu|S+ w"}/oU2-OѺinK1QR굥a_ץN/m+=oubdG .=e٫/ M-҂Q)@rAq7y_aJ u OAcTjw鶮cTġ q2WA5% y*d?/b BD>.ќП1O\u{…'!<&oWpfbK_TO}jMP\fC~_U}`i0کnڡeϾ3[^]y\Q}KmySPg([ 'ozc_݄buOrcaWvGa /#<ݍN2Ԍ?HgUR<"Nyfl6$&M~}꺽F0oʝW=S{,C'4Dnk1) ;:rXPQmi,}wժ:ҽQZ/_7E'פ͉[[U#C1)S<Cj$#:|]LfÒ_7VazIobUoXߟpsv%9 0y&.jd{l3݉0B7)b]޷U\5vLAq$l j(Ls* 1 ]o x hKznx$`= H]jENƭ"')2!JLdt 27PZOo.VwB_2 `yņ$ ;Qo`J.Z8mv^@^q`e6O-Ǧ|$Zx1c[7m];&endstream endobj 620 0 obj << /Type /XRef /Length 336 /Filter /FlateDecode /DecodeParms << /Columns 5 /Predictor 12 >> /W [ 1 3 1 ] /Info 93 0 R /Root 92 0 R /Size 621 /ID [<90738b6ce40719da90da9ad0637cd9bf>] >> stream xcb&F~0 $8J8 B'ټ4c4͌ӌ^R`jm4S7ZJ- 4 %@1E6* RT.F-Ad `y/h % @_hj%vˁ)$Bv4SvCPƗ J-| &d Lfk Rv&HN7/ fۃH- kÕ`sHW1r m*tsו/AW@*؂v= a`5`/J@Z\VDru٫`:= d>="w G endstream endobj startxref 411280 %%EOF RProtoBuf/inst/doc/RProtoBuf-paper.R0000644000176200001440000003103313164671420016774 0ustar liggesusers### R code from vignette source 'RProtoBuf-paper.Rnw' ################################################### ### code chunk number 1: prelim ################################################### library(RProtoBuf) rprotobuf.version <- packageDescription("RProtoBuf")$Version rprotobuf.date <- packageDescription("RProtoBuf")$Date now.date <- strftime(Sys.Date(), "%B %d, %Y") ################################################### ### code chunk number 2: RProtoBuf-paper.Rnw:126-132 ################################################### ## cf http://www.jstatsoft.org/style#q12 options(prompt = "R> ", continue = "+ ", width = 70, useFancyQuotes = FALSE, digits = 4) ################################################### ### code chunk number 3: RProtoBuf-paper.Rnw:326-334 ################################################### library("RProtoBuf") p <- new(tutorial.Person, id=1, name="Dirk") p$name p$name <- "Murray" cat(as.character(p)) serialize(p, NULL) class(p) ################################################### ### code chunk number 4: RProtoBuf-paper.Rnw:414-415 ################################################### p <- new(tutorial.Person, name = "Murray", id = 1) ################################################### ### code chunk number 5: RProtoBuf-paper.Rnw:424-427 ################################################### p$name p$id p$email <- "murray@stokely.org" ################################################### ### code chunk number 6: RProtoBuf-paper.Rnw:435-438 ################################################### p[["name"]] <- "Murray Stokely" p[[ 2 ]] <- 3 p[["email"]] ################################################### ### code chunk number 7: RProtoBuf-paper.Rnw:452-453 ################################################### p ################################################### ### code chunk number 8: RProtoBuf-paper.Rnw:460-461 ################################################### writeLines(as.character(p)) ################################################### ### code chunk number 9: RProtoBuf-paper.Rnw:474-475 ################################################### serialize(p, NULL) ################################################### ### code chunk number 10: RProtoBuf-paper.Rnw:480-483 ################################################### tf1 <- tempfile() serialize(p, tf1) readBin(tf1, raw(0), 500) ################################################### ### code chunk number 11: RProtoBuf-paper.Rnw:500-502 ################################################### msg <- read(tutorial.Person, tf1) writeLines(as.character(msg)) ################################################### ### code chunk number 12: RProtoBuf-paper.Rnw:592-593 ################################################### new(tutorial.Person) ################################################### ### code chunk number 13: RProtoBuf-paper.Rnw:617-622 ################################################### tutorial.Person$email tutorial.Person$email$is_required() tutorial.Person$email$type() tutorial.Person$email$as.character() class(tutorial.Person$email) ################################################### ### code chunk number 14: RProtoBuf-paper.Rnw:634-641 ################################################### tutorial.Person$PhoneType tutorial.Person$PhoneType$WORK class(tutorial.Person$PhoneType) tutorial.Person$PhoneType$value(1) tutorial.Person$PhoneType$value(name="HOME") tutorial.Person$PhoneType$value(number=1) class(tutorial.Person$PhoneType$value(1)) ################################################### ### code chunk number 15: RProtoBuf-paper.Rnw:737-740 ################################################### if (!exists("JSSPaper.Example1", "RProtoBuf:DescriptorPool")) { readProtoFiles(file="proto/int64.proto") } ################################################### ### code chunk number 16: RProtoBuf-paper.Rnw:762-766 ################################################### as.integer(2^31-1) as.integer(2^31 - 1) + as.integer(1) 2^31 class(2^31) ################################################### ### code chunk number 17: RProtoBuf-paper.Rnw:778-779 ################################################### 2^53 == (2^53 + 1) ################################################### ### code chunk number 18: RProtoBuf-paper.Rnw:816-818 ################################################### msg <- serialize_pb(iris, NULL) identical(iris, unserialize_pb(msg)) ################################################### ### code chunk number 19: RProtoBuf-paper.Rnw:846-849 ################################################### datasets <- as.data.frame(data(package="datasets")$results) datasets$name <- sub("\\s+.*$", "", datasets$Item) n <- nrow(datasets) ################################################### ### code chunk number 20: RProtoBuf-paper.Rnw:867-910 ################################################### datasets$object.size <- unname(sapply(datasets$name, function(x) object.size(eval(as.name(x))))) datasets$R.serialize.size <- unname(sapply(datasets$name, function(x) length(serialize(eval(as.name(x)), NULL)))) datasets$R.serialize.size <- unname(sapply(datasets$name, function(x) length(serialize(eval(as.name(x)), NULL)))) datasets$R.serialize.size.gz <- unname(sapply(datasets$name, function(x) length(memCompress(serialize(eval(as.name(x)), NULL), "gzip")))) datasets$RProtoBuf.serialize.size <- unname(sapply(datasets$name, function(x) length(serialize_pb(eval(as.name(x)), NULL)))) datasets$RProtoBuf.serialize.size.gz <- unname(sapply(datasets$name, function(x) length(memCompress(serialize_pb(eval(as.name(x)), NULL), "gzip")))) clean.df <- data.frame(dataset=datasets$name, object.size=datasets$object.size, "serialized"=datasets$R.serialize.size, "gzipped serialized"=datasets$R.serialize.size.gz, "RProtoBuf"=datasets$RProtoBuf.serialize.size, "gzipped RProtoBuf"=datasets$RProtoBuf.serialize.size.gz, "ratio.serialized" = datasets$R.serialize.size / datasets$object.size, "ratio.rprotobuf" = datasets$RProtoBuf.serialize.size / datasets$object.size, "ratio.serialized.gz" = datasets$R.serialize.size.gz / datasets$object.size, "ratio.rprotobuf.gz" = datasets$RProtoBuf.serialize.size.gz / datasets$object.size, "savings.serialized" = 1-(datasets$R.serialize.size / datasets$object.size), "savings.rprotobuf" = 1-(datasets$RProtoBuf.serialize.size / datasets$object.size), "savings.serialized.gz" = 1-(datasets$R.serialize.size.gz / datasets$object.size), "savings.rprotobuf.gz" = 1-(datasets$RProtoBuf.serialize.size.gz / datasets$object.size), check.names=FALSE) all.df<-data.frame(dataset="TOTAL", object.size=sum(datasets$object.size), "serialized"=sum(datasets$R.serialize.size), "gzipped serialized"=sum(datasets$R.serialize.size.gz), "RProtoBuf"=sum(datasets$RProtoBuf.serialize.size), "gzipped RProtoBuf"=sum(datasets$RProtoBuf.serialize.size.gz), "ratio.serialized" = sum(datasets$R.serialize.size) / sum(datasets$object.size), "ratio.rprotobuf" = sum(datasets$RProtoBuf.serialize.size) / sum(datasets$object.size), "ratio.serialized.gz" = sum(datasets$R.serialize.size.gz) / sum(datasets$object.size), "ratio.rprotobuf.gz" = sum(datasets$RProtoBuf.serialize.size.gz) / sum(datasets$object.size), "savings.serialized" = 1-(sum(datasets$R.serialize.size) / sum(datasets$object.size)), "savings.rprotobuf" = 1-(sum(datasets$RProtoBuf.serialize.size) / sum(datasets$object.size)), "savings.serialized.gz" = 1-(sum(datasets$R.serialize.size.gz) / sum(datasets$object.size)), "savings.rprotobuf.gz" = 1-(sum(datasets$RProtoBuf.serialize.size.gz) / sum(datasets$object.size)), check.names=FALSE) clean.df<-rbind(clean.df, all.df) ################################################### ### code chunk number 21: SER ################################################### old.mar<-par("mar") new.mar<-old.mar new.mar[3]<-0 new.mar[4]<-0 my.cex<-1.3 par("mar"=new.mar) plot(clean.df$savings.serialized, clean.df$savings.rprotobuf, pch=1, col="red", las=1, xlab="Serialization Space Savings", ylab="Protocol Buffer Space Savings", xlim=c(0,1),ylim=c(0,1),cex.lab=my.cex, cex.axis=my.cex) points(clean.df$savings.serialized.gz, clean.df$savings.rprotobuf.gz,pch=2, col="blue") # grey dotted diagonal abline(a=0,b=1, col="grey",lty=2,lwd=3) # find point furthest off the X axis. clean.df$savings.diff <- clean.df$savings.serialized - clean.df$savings.rprotobuf clean.df$savings.diff.gz <- clean.df$savings.serialized.gz - clean.df$savings.rprotobuf.gz # The one to label. tmp.df <- clean.df[which(clean.df$savings.diff == min(clean.df$savings.diff)),] # This minimum means most to the left of our line, so pos=2 is label to the left text(tmp.df$savings.serialized, tmp.df$savings.rprotobuf, labels=tmp.df$dataset, pos=2, cex=my.cex) # Some gziped version # text(tmp.df$savings.serialized.gz, tmp.df$savings.rprotobuf.gz, labels=tmp.df$dataset, pos=2, cex=my.cex) # Second one is also an outlier tmp.df <- clean.df[which(clean.df$savings.diff == sort(clean.df$savings.diff)[2]),] # This minimum means most to the left of our line, so pos=2 is label to the left text(tmp.df$savings.serialized, tmp.df$savings.rprotobuf, labels=tmp.df$dataset, pos=2, cex=my.cex) #text(tmp.df$savings.serialized.gz, tmp.df$savings.rprotobuf.gz, labels=tmp.df$dataset, pos=my.cex) tmp.df <- clean.df[which(clean.df$savings.diff == max(clean.df$savings.diff)),] # This minimum means most to the right of the diagonal, so pos=4 is label to the right # Only show the gziped one. #text(tmp.df$savings.serialized, tmp.df$savings.rprotobuf, labels=tmp.df$dataset, pos=4, cex=my.cex) text(tmp.df$savings.serialized.gz, tmp.df$savings.rprotobuf.gz, labels=tmp.df$dataset, pos=4, cex=my.cex) #outlier.dfs <- clean.df[c(which(clean.df$savings.diff == min(clean.df$savings.diff)), legend("topleft", c("Raw", "Gzip Compressed"), pch=1:2, col=c("red", "blue"), cex=my.cex) #interesting.df <- clean.df[unique(c(which(clean.df$savings.diff == min(clean.df$savings.diff)), # which(clean.df$savings.diff == max(clean.df$savings.diff)), # which(clean.df$savings.diff.gz == max(clean.df$savings.diff.gz)), # which(clean.df$dataset == "TOTAL"))),c("dataset", "object.size", "serialized", "gzipped serialized", "RProtoBuf", "gzipped RProtoBuf", "savings.serialized", "savings.serialized.gz", "savings.rprotobuf", "savings.rprotobuf.gz")] interesting.df <- clean.df[as.character(clean.df[,1]) %in% c("crimtab", "airquality", "faithful", "TOTAL"), c("dataset", "object.size", "serialized", "gzipped serialized", "RProtoBuf", "gzipped RProtoBuf", "savings.serialized", "savings.serialized.gz", "savings.rprotobuf", "savings.rprotobuf.gz")] interesting.df <- interesting.df[c(2,1,3,4),] # Print without .00 in xtable interesting.df$object.size <- as.integer(interesting.df$object.size) par("mar"=old.mar) ################################################### ### code chunk number 22: RProtoBuf-paper.Rnw:1174-1178 (eval = FALSE) ################################################### ## require(HistogramTools) ## readProtoFiles(package="HistogramTools") ## hist <- HistogramTools.HistogramState$read("proto/hist.pb") ## plot(as.histogram(hist), main="") ################################################### ### code chunk number 23: RProtoBuf-paper.Rnw:1265-1272 (eval = FALSE) ################################################### ## library("RProtoBuf") ## library("httr") ## ## req <- GET('https://demo.ocpu.io/MASS/data/Animals/pb') ## output <- unserialize_pb(req$content) ## ## identical(output, MASS::Animals) ################################################### ### code chunk number 24: RProtoBuf-paper.Rnw:1324-1340 (eval = FALSE) ################################################### ## library("httr") ## library("RProtoBuf") ## ## args <- list(n=42, mean=100) ## payload <- serialize_pb(args, NULL) ## ## req <- POST ( ## url = "https://demo.ocpu.io/stats/R/rnorm/pb", ## body = payload, ## add_headers ( ## "Content-Type" = "application/x-protobuf" ## ) ## ) ## ## output <- unserialize_pb(req$content) ## print(output) ################################################### ### code chunk number 25: RProtoBuf-paper.Rnw:1344-1347 (eval = FALSE) ################################################### ## fnargs <- unserialize_pb(inputmsg) ## val <- do.call(stats::rnorm, fnargs) ## outputmsg <- serialize_pb(val) RProtoBuf/inst/doc/RProtoBuf-intro.Rmd0000644000176200001440000021244313164231540017342 0ustar liggesusers--- title: | | \pkg{RProtoBuf}: An R API for Protocol Buffers # Use letters for affiliations author: - name: Dirk Eddelbuettel affiliation: a - name: Romain François affiliation: b - name: Murray Stokely affiliation: c address: - code: a address: \url{http://dirk.eddelbuettel.com} - code: b address: \url{https://romain.rbind.io/} - code: c address: \url{https://stokely.org} # For footer text lead_author_surname: Eddelbuettel, François and Stokely # Place DOI URL or CRAN Package URL here doi: "https://cran.r-project.org/package=RProtoBuf" # Customize footer, eg by referencing the vignette footer_contents: "RProtoBuf Vignette" # Abstract abstract: | \textsl{Protocol Buffers} is a software project by Google that is used extensively internally and also released under an Open Source license. It provides a way of encoding structured data in an efficient yet extensible format. Google formally supports APIs for C++, Java and Python. This vignette describes version the \texttt{RProtoBuf} package which brings support for Protocol Buffer messages to R. # Font size of the document, values of 9pt (default), 10pt, 11pt and 12pt fontsize: 10pt # Optional: Force one-column layout, default is two-column one_column: true # Optional: Enable section numbering, default is unnumbered numbersections: true # Optional: Specify the depth of section number, default is 5 secnumdepth: 5 # Produce a pinp document output: pinp::pinp # Optional extra LaTeX definitions header-includes: > \newcommand{\proglang}[1]{\textsf{#1}} \newcommand{\pkg}[1]{\textbf{#1}} \newcommand{\faq}[1]{FAQ~\ref{#1}} \newcommand{\rdoc}[2]{\href{http://www.rdocumentation.org/packages/#1/functions/#2}{\code{#2}}} \newcommand{\sugar}{\textsl{Rcpp sugar}~} # Declarations for R vignette indices vignette: > %\VignetteIndexEntry{RProtoBuf-intro} %\VignetteKeywords{RProtoBuf, Protocol Buffers, package} %\VignetteDepends{RProtoBuf} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r init, echo=FALSE} library("RProtoBuf") options("width"=90) ``` \tableofcontents # Protocol Buffers Protocol Buffers are a language-neutral, platform-neutral, extensible way of serializing structured data for use in communications protocols, data storage, and more. Protocol Buffers offer key features such as an efficient data interchange format that is both language- and operating system-agnostic yet uses a lightweight and highly performant encoding, object serialization and de-serialization as well data and configuration management. Protocol Buffers are also forward compatible: updates to the \texttt{proto} files do not break programs built against the previous specification. While benchmarks are not available, Google states on the project page that in comparison to XML, Protocol Buffers are at the same time \textsl{simpler}, between three to ten times \textsl{smaller}, between twenty and one hundred times \textsl{faster}, as well as less ambiguous and easier to program. The Protocol Buffers code is released under an open-source (BSD) license. The Protocol Buffer project (\url{http://code.google.com/p/protobuf/}) contains a C++ library and a set of runtime libraries and compilers for C++, Java and Python. With these languages, the workflow follows standard practice of so-called Interface Description Languages (IDL) (c.f. \href{http://en.wikipedia.org/wiki/Interface_description_language}{Wikipedia on IDL}). This consists of compiling a Protocol Buffer description file (ending in \texttt{.proto}) into language specific classes that can be used to create, read, write and manipulate Protocol Buffer messages. In other words, given the 'proto' description file, code is automatically generated for the chosen target language(s). The project page contains a tutorial for each of these officially supported languages: \url{http://code.google.com/apis/protocolbuffers/docs/tutorials.html} Besides the officially supported C++, Java and Python implementations, several projects have been created to support Protocol Buffers for many languages. The list of known languages to support protocol buffers is compiled as part of the project page: \url{http://code.google.com/p/protobuf/wiki/ThirdPartyAddOns} The Protocol Buffer project page contains a comprehensive description of the language: \url{http://code.google.com/apis/protocolbuffers/docs/proto.html} # Basic use: Protocol Buffers and R This section describes how to use the R API to create and manipulate protocol buffer messages in R, and how to read and write the binary \emph{payload} of the messages to files and arbitrary binary R connections. ## Importing proto files dynamically In contrast to the other languages (Java, C++, Python) that are officially supported by Google, the implementation used by the \texttt{RProtoBuf} package does not rely on the \texttt{protoc} compiler (with the exception of the two functions discussed in the previous section). This means that no initial step of statically compiling the proto file into C++ code that is then accessed by R code is necessary. Instead, \texttt{proto} files are parsed and processed \textsl{at runtime} by the protobuf C++ library---which is much more appropriate for a dynamic language. The \texttt{readProtoFiles} function allows importing \texttt{proto} files in several ways. ```{r readproto} args(readProtoFiles) ``` Using the \texttt{file} argument, one can specify one or several file paths that ought to be proto files. ```{r loadprotos, eval=FALSE} pdir <- system.file("proto", package = "RProtoBuf") pfile <- file.path(pdir, "addressbook.proto") readProtoFiles(pfile) ``` With the \texttt{dir} argument, which is ignored if the \texttt{file} is supplied, all files matching the \texttt{.proto} extension will be imported. ```{r readir, eval=FALSE} dir(pdir, pattern = "\\.proto$", full.names = TRUE) readProtoFiles(dir = pdir) ``` Finally, with the \texttt{package} argument (ignored if \texttt{file} or \texttt{dir} is supplied), the function will import all \texttt{.proto} files that are located in the \texttt{proto} sub-directory of the given package. A typical use for this argument is in the \texttt{.onLoad} function of a package. ```{r protofrompackage, eval=FALSE} readProtoFiles( package = "RProtoBuf" ) ``` Once the proto files are imported, all message descriptors are available in the R search path in the \texttt{RProtoBuf:DescriptorPool} special environment. The underlying mechanism used here is described in more detail in section~\ref{sec-lookup}. ```{r lsproto} ls("RProtoBuf:DescriptorPool") ``` ## Creating a message The objects contained in the special environment are descriptors for their associated message types. Descriptors will be discussed in detail in another part of this document, but for the purpose of this section, descriptors are just used with the \texttt{new} function to create messages. ```{r newmsg} p <- new(tutorial.Person, name = "Romain", id = 1) ``` ## Access and modify fields of a message Once the message is created, its fields can be queried and modified using the dollar operator of R, making protocol buffer messages seem like lists. ```{r modmsg} p$name p$id p$email <- "francoisromain@free.fr" ``` However, as opposed to R lists, no partial matching is performed and the name must be given entirely. The \verb|[[| operator can also be used to query and set fields of a message, supplying either their name or their tag number : ```{r modfields} p[["name"]] <- "Romain Francois" p[[ 2 ]] <- 3 p[[ "email" ]] ``` Protocol buffers include a 64-bit integer type, but R lacks native 64-bit integer support. A workaround is available and described in Section~\ref{sec:int64} for working with large integer values. ## Display messages Protocol buffer messages and descriptors implement \texttt{show} methods that provide basic information about the message : ```{r msgdisp} p ``` For additional information, such as for debugging purposes, the \texttt{as.character} method provides a more complete ASCII representation of the contents of a message. ```{r writeaschar} cat(as.character(p)) ``` ## Serializing messages However, the main focus of protocol buffer messages is efficiency. Therefore, messages are transported as a sequence of bytes. The \texttt{serialize} method is implemented for protocol buffer messages to serialize a message into the sequence of bytes (raw vector in R speech) that represents the message. ```{r serial1} serialize( p, NULL ) ``` The same method can also be used to serialize messages to files : ```{r serial2} tf1 <- tempfile() tf1 serialize( p, tf1 ) readBin(tf1, raw(0), 500) ``` Or to arbitrary binary connections: ```{r serial3} tf2 <- tempfile() con <- file(tf2, open = "wb") serialize(p, con) close(con) readBin(tf2, raw(0), 500) ``` \texttt{serialize} can also be used in a more traditional object oriented fashion using the dollar operator : ```{r serial4} # serialize to a file p$serialize(tf1) # serialize to a binary connection con <- file(tf2, open = "wb") p$serialize(con) close(con) ``` ## Parsing messages The \texttt{RProtoBuf} package defines the \texttt{read} function to read messages from files, raw vector (the message payload) and arbitrary binary connections. ```{r parse1} args(read) ``` The binary representation of the message (often called the payload) does not contain information that can be used to dynamically infer the message type, so we have to provide this information to the \texttt{read} function in the form of a descriptor : ```{r parse2} message <- read(tutorial.Person, tf1) cat(as.character(message)) ``` The \texttt{input} argument of \texttt{read} can also be a binary readable R connection, such as a binary file connection: ```{r parse3} con <- file(tf2, open = "rb") message <- read(tutorial.Person, con) close(con) cat(as.character(message)) ``` Finally, the payload of the message can be used : ```{r parse4} # reading the raw vector payload of the message payload <- readBin(tf1, raw(0), 5000) message <- read( tutorial.Person, payload ) ``` \texttt{read} can also be used as a pseudo method of the descriptor object : ```{r parse5} # reading from a file message <- tutorial.Person$read(tf1) # reading from a binary connection con <- file(tf2, open = "rb") message <- tutorial.Person$read(con) close(con) # read from the payload message <- tutorial.Person$read(payload) ``` ## Classes, Methods and Pseudo Methods The \texttt{RProtoBuf} package uses the S4 system to store information about descriptors and messages, but the information stored in the R object is very minimal and mainly consists of an external pointer to a C++ variable that is managed by the \texttt{proto} C++ library. ```{r classes1, eval=FALSE} str(p) ``` Using the S4 system allows the \texttt{RProtoBuf} package to dispatch methods that are not generic in the S3 sense, such as \texttt{new} and \texttt{serialize}. The \texttt{RProtoBuf} package combines the \emph{R typical} dispatch of the form \verb|method( object, arguments)| and the more traditional object oriented notation \verb|object$method(arguments)|. ## Messages Messages are represented in R using the \texttt{Message} S4 class. The class contains the slots \texttt{pointer} and \texttt{type} as described on the Table~\ref{Message-class-table}. \begin{table}[h] \centering \begin{tabular}{|cp{10cm}|} \hline \textbf{slot} & \textbf{description} \\ \hline \texttt{pointer} & external pointer to the \texttt{Message} object of the C++ proto library. Documentation for the \texttt{Message} class is available from the protocol buffer project page: \url{http://code.google.com/apis/protocolbuffers/docs/reference/cpp/google.protobuf.message.html#Message} \\ \hline \texttt{type} & fully qualified path of the message. For example a \texttt{Person} message has its \texttt{type} slot set to \texttt{tutorial.Person} \\ \hline \end{tabular} \caption{\label{Message-class-table}Description of slots for the \texttt{Message} S4 class} \end{table} Although the \texttt{RProtoBuf} package uses the S4 system, the \verb|@| operator is very rarely used. Fields of the message are retrieved or modified using the \verb|$| or \verb|[[| operators as seen on the previous section, and pseudo-methods can also be called using the \verb|$| operator. Table~\ref{Message-methods-table} describes the methods defined for the \texttt{Message} class : \begin{table}[h] \centering \begin{small} \begin{tabular}{|ccp{8cm}|} \hline \textbf{method} & \textbf{section} & \textbf{description} \\ \hline \hline \texttt{has} & \ref{Message-method-has} & Indicates if a message has a given field. \\ \texttt{clone} & \ref{Message-method-clone} & Creates a clone of the message \\ \texttt{isInitialized} & \ref{Message-method-isInitialized} & Indicates if a message has all its required fields set\\ \texttt{serialize} & \ref{Message-method-serialize} & serialize a message to a file or a binary connection or retrieve the message payload as a raw vector\\ \texttt{clear} & \ref{Message-method-clear} & Clear one or several fields of a message, or the entire message\\ \texttt{size} & \ref{Message-method-size} & The number of elements in a message field\\ \texttt{bytesize} & \ref{Message-method-bytesize} & The number of bytes the message would take once serialized\\ \hline \texttt{swap} & \ref{Message-method-swap} & swap elements of a repeated field of a message\\ \texttt{set} & \ref{Message-method-set} & set elements of a repeated field\\ \texttt{fetch} & \ref{Message-method-fetch} & fetch elements of a repeated field\\ \texttt{setExtension} & \ref{Message-method-setExtension} & set an extension of a message\\ \texttt{getExtension} & \ref{Message-method-getExtension} & get the value of an extension of a message\\ \texttt{add} & \ref{Message-method-add} & add elements to a repeated field \\ \hline \texttt{str} & \ref{Message-method-str} & the R structure of the message\\ \texttt{as.character} & \ref{Message-method-ascharacter} & character representation of a message\\ \texttt{toString} & \ref{Message-method-toString} & character representation of a message (same as \texttt{as.character}) \\ \texttt{as.list} & \ref{Message-method-aslist} & converts message to a named R list\\ \texttt{update} & \ref{Message-method-update} & updates several fields of a message at once\\ \texttt{descriptor} & \ref{Message-method-descriptor} & get the descriptor of the message type of this message\\ \texttt{fileDescriptor} & \ref{Message-method-fileDescriptor} & get the file descriptor of this message's descriptor\\ \hline \end{tabular} \end{small} \caption{\label{Message-methods-table}Description of methods for the \texttt{Message} S4 class} \end{table} ### Retrieve fields \label{Message-method-getfield} The \verb|$| and \verb|[[| operators allow extraction of a field data. ```{r retrieve} message <- new(tutorial.Person, name = "foo", email = "foo@bar.com", id = 2, phone = list(new(tutorial.Person.PhoneNumber, number = "+33(0)...", type = "HOME"), new(tutorial.Person.PhoneNumber, number = "+33(0)###", type = "MOBILE") ) ) message$name message$email message[["phone"]] # using the tag number message[[2]] # id ``` Neither \verb|$| nor \verb|[[| support partial matching of names. The \verb|$| is also used to call methods on the message, and the \verb|[[| operator can use the tag number of the field. Table~\ref{table-get-types} details correspondence between the field type and the type of data that is retrieved by \verb|$| and \verb|[[|. \begin{table}[h] \centering \begin{small} \begin{tabular}{|c|p{5cm}p{5cm}|} \hline field type & R type (non repeated) & R type (repeated) \\ \hline \hline double & \texttt{double} vector & \texttt{double} vector \\ float & \texttt{double} vector & \texttt{double} vector \\ \hline uint32 & \texttt{double} vector & \texttt{double} vector \\ fixed32 & \texttt{double} vector & \texttt{double} vector \\ \hline int32 & \texttt{integer} vector & \texttt{integer} vector \\ sint32 & \texttt{integer} vector & \texttt{integer} vector \\ sfixed32 & \texttt{integer} vector & \texttt{integer} vector \\ \hline int64 & \texttt{integer} or \texttt{character} vector \footnotemark & \texttt{integer} or \texttt{character} vector \\ uint64 & \texttt{integer} or \texttt{character} vector & \texttt{integer} or \texttt{character} vector \\ sint64 & \texttt{integer} or \texttt{character} vector & \texttt{integer} or \texttt{character} vector \\ fixed64 & \texttt{integer} or \texttt{character} vector & \texttt{integer} or \texttt{character} vector \\ sfixed64 & \texttt{integer} or \texttt{character} vector & \texttt{integer} or \texttt{character} vector \\ \hline bool & \texttt{logical} vector & \texttt{logical} vector \\ \hline string & \texttt{character} vector & \texttt{character} vector \\ bytes & \texttt{character} vector & \texttt{character} vector \\ \hline enum & \texttt{integer} vector & \texttt{integer} vector \\ \hline message & \texttt{S4} object of class \texttt{Message} & \texttt{list} of \texttt{S4} objects of class \texttt{Message} \\ \hline \end{tabular} \end{small} \caption{\label{table-get-types}Correspondence between field type and R type retrieved by the extractors. \footnotesize{1. R lacks native 64-bit integers, so the \texttt{RProtoBuf.int64AsString} option is available to return large integers as characters to avoid losing precision. This option is described in Section~\ref{sec:int64}}. R also lacks an unsigned integer type.} \end{table} ### Modify fields \label{Message-method-setfield} The \verb|$<-| and \verb|[[<-| operators are implemented for \texttt{Message} objects to set the value of a field. The R data is coerced to match the type of the message field. ```{r modify} message <- new(tutorial.Person, name = "foo", id = 2) message$email <- "foo@bar.com" message[["id"]] <- 42 message[[1]] <- "foobar" cat(message$as.character()) ``` Table~\ref{table-message-field-setters} describes the R types that are allowed in the right hand side depending on the target type of the field. \begin{table}[h] \centering \begin{small} \begin{tabular}{|p{5cm}|p{7cm}|} \hline internal type & allowed R types \\ \hline \hline \texttt{double}, \texttt{float} & \texttt{integer}, \texttt{raw}, \texttt{double}, \texttt{logical} \\ \hline \texttt{int32}, \texttt{int64}, \texttt{uint32}, \texttt{uint64}, \texttt{sint32}, \texttt{sint64}, \texttt{fixed32}, \texttt{fixed64}, \texttt{sfixed32}, \texttt{sfixed64} & \texttt{integer}, \texttt{raw}, \texttt{double}, \texttt{logical}, \texttt{character} \\ \hline \texttt{bool} & \texttt{integer}, \texttt{raw}, \texttt{double}, \texttt{logical} \\ \hline \texttt{bytes}, \texttt{string} & \texttt{character} \\ \hline \texttt{enum} & \texttt{integer}, \texttt{double}, \texttt{raw}, \texttt{character} \\ \hline \texttt{message}, \texttt{group} & \texttt{S4}, of class \texttt{Message} of the appropriate message type, or a \texttt{list} of \texttt{S4} objects of class \texttt{Message} of the appropriate message type.\\ \hline \end{tabular} \end{small} \caption{\label{table-message-field-setters}Allowed R types depending on internal field types. } \end{table} ### Message\$has method \label{Message-method-has} The \texttt{has} method indicates if a field of a message is set. For repeated fields, the field is considered set if there is at least on object in the array. For non-repeated fields, the field is considered set if it has been initialized. The \texttt{has} method is a thin wrapper around the \texttt{HasField} and \texttt{FieldSize} methods of the \texttt{google::protobuf::Reflection} C++ class. ```{r has} message <- new(tutorial.Person, name = "foo") message$has("name") message$has("id") message$has("phone") ``` ### Message\$clone method \label{Message-method-clone} The \texttt{clone} function creates a new message that is a clone of the message. This function is a wrapper around the methods \texttt{New} and \texttt{CopyFrom} of the \texttt{google::protobuf::Message} C++ class. ```{r methodclone} m1 <- new(tutorial.Person, name = "foo") m2 <- m1$clone() m2$email <- "foo@bar.com" cat(as.character(m1)) cat(as.character(m2)) ``` ### Message\$isInitialized method \label{Message-method-isInitialized} The \texttt{isInitialized} method quickly checks if all required fields have values set. This is a thin wrapper around the \texttt{IsInitialized} method of the \texttt{google::protobuf::Message} C++ class. ```{r methodisinit} message <- new(tutorial.Person, name = "foo") message$isInitialized() message$id <- 2 message$isInitialized() ``` ### Message\$serialize method \label{Message-method-serialize} The \texttt{serialize} method can be used to serialize the message as a sequence of bytes into a file or a binary connection. ```{r messageserialize1} message <- new(tutorial.Person, name = "foo", email = "foo@bar.com", id = 2) tf1 <- tempfile() tf1 message$serialize(tf1) tf2 <- tempfile() tf2 con <- file(tf2, open = "wb") message$serialize(con) close(con) ``` The (temporary) files `tf1` and `tf2` both contain the message payload as a sequence of bytes. The \texttt{readBin} function can be used to read the files as a raw vector in R: ```{r messageserialize2} readBin(tf1, raw(0), 500) readBin(tf2, raw(0), 500) ``` The \texttt{serialize} method can also be used to directly retrieve the payload of the message as a raw vector: ```{r messageserialize3} message$serialize(NULL) ``` ### Message\$clear method \label{Message-method-clear} The \texttt{clear} method can be used to clear all fields of a message when used with no argument, or a given field. ```{r messageclear} message <- new(tutorial.Person, name = "foo", email = "foo@bar.com", id = 2) cat(as.character(message)) message$clear() cat(as.character(message)) message <- new(tutorial.Person, name = "foo", email = "foo@bar.com", id = 2) message$clear("id") cat(as.character(message)) ``` The \texttt{clear} method is a thin wrapper around the \texttt{Clear} method of the \texttt{google::protobuf::Message} C++ class. ### Message\$size method \label{Message-method-size} The \texttt{size} method is used to query the number of objects in a repeated field of a message : ```{r messagesize} message <- new(tutorial.Person, name = "foo", phone = list(new(tutorial.Person.PhoneNumber, number = "+33(0)...", type = "HOME"), new(tutorial.Person.PhoneNumber, number = "+33(0)###", type = "MOBILE") )) message$size("phone") size( message, "phone") ``` The \texttt{size} method is a thin wrapper around the \texttt{FieldSize} method of the \texttt{google::protobuf::Reflection} C++ class. ### Message\$bytesize method \label{Message-method-bytesize} The \texttt{bytesize} method retrieves the number of bytes the message would take once serialized. This is a thin wrapper around the \texttt{ByteSize} method of the \texttt{google::protobuf::Message} C++ class. ```{r messagebytesize} message <- new(tutorial.Person, name = "foo", email = "foo@bar.com", id = 2) message$bytesize() bytesize(message) length(message$serialize(NULL)) ``` ### Message\$swap method \label{Message-method-swap} The \texttt{swap} method can be used to swap elements of a repeated field. ```{r messageswap} message <- new(tutorial.Person, name = "foo", phone = list(new(tutorial.Person.PhoneNumber, number = "+33(0)...", type = "HOME" ), new(tutorial.Person.PhoneNumber, number = "+33(0)###", type = "MOBILE" ))) message$swap("phone", 1, 2) cat(as.character(message$phone[[1]])) cat(as.character(message$phone[[2]])) swap(message, "phone", 1, 2) cat(as.character(message$phone[[1]])) cat(as.character(message$phone[[2]])) ``` ### Message\$set method \label{Message-method-set} The \texttt{set} method can be used to set values of a repeated field. ```{r messagset} message <- new(tutorial.Person, name = "foo", phone = list(new(tutorial.Person.PhoneNumber, number = "+33(0)...", type = "HOME"), new(tutorial.Person.PhoneNumber, number = "+33(0)###", type = "MOBILE"))) number <- new(tutorial.Person.PhoneNumber, number = "+33(0)---", type = "WORK") message$set("phone", 1, number) cat(as.character( message)) ``` ### Message\$fetch method \label{Message-method-fetch} The \texttt{fetch} method can be used to get values of a repeated field. ```{r messagefetch} message <- new(tutorial.Person, name = "foo", phone = list(new(tutorial.Person.PhoneNumber, number = "+33(0)...", type = "HOME"), new(tutorial.Person.PhoneNumber, number = "+33(0)###", type = "MOBILE" ))) message$fetch("phone", 1) ``` ### Message\$setExtension method \label{Message-method-setExtension} The \texttt{setExtension} method can be used to set an extension field of the Message. ```{r messageset} if (!exists("protobuf_unittest.TestAllTypes", "RProtoBuf:DescriptorPool")) { unittest.proto.file <- system.file("unitTests", "data", "unittest.proto", package="RProtoBuf") readProtoFiles(file=unittest.proto.file) } ## Test setting a singular extensions. test <- new(protobuf_unittest.TestAllExtensions) test$setExtension(protobuf_unittest.optional_int32_extension, as.integer(1)) ``` ### Message\$getExtension method \label{Message-method-getExtension} The \texttt{getExtension} method can be used to get values of an extension. ```{r messagegetextension} test$getExtension(protobuf_unittest.optional_int32_extension) ``` ### Message\$add method \label{Message-method-add} The \texttt{add} method can be used to add values to a repeated field. ```{r messageadd} message <- new(tutorial.Person, name = "foo") phone <- new(tutorial.Person.PhoneNumber, number = "+33(0)...", type = "HOME") message$add("phone", phone) cat(message$toString()) ``` ### Message\$str method \label{Message-method-str} The \texttt{str} method gives the R structure of the message. This is rarely useful. ```{r messagestr} message <- new(tutorial.Person, name = "foo", email = "foo@bar.com", id = 2) message$str() str(message) ``` ### Message\$as.character method \label{Message-method-ascharacter} The \texttt{as.character} method gives the debug string of the message. ```{r messageascharacter} message <- new(tutorial.Person, name = "foo", email = "foo@bar.com", id = 2) cat(message$as.character()) cat(as.character(message)) ``` ### Message\$toString method \label{Message-method-toString} \texttt{toString} currently is an alias to the \texttt{as.character} function. ```{r messagetostring} message <- new(tutorial.Person, name = "foo", email = "foo@bar.com", id = 2) cat(message$toString()) cat(toString( message)) ``` ### Message\$as.list method \label{Message-method-aslist} The \texttt{as.list} method converts the message to a named R list. ```{r messageaslist} message <- new(tutorial.Person, name = "foo", email = "foo@bar.com", id = 2) as.list(message) ``` The names of the list are the names of the declared fields of the message type, and the content is the same as can be extracted with the \verb|$| operator described in section~\ref{Message-method-getfield}. ### Message\$update method \label{Message-method-update} The \texttt{update} method can be used to update several fields of a message at once. ```{r messageupdate} message <- new(tutorial.Person) update(message, name = "foo", id = 2, email = "foo@bar.com") cat(message$as.character()) ``` ### Message\$descriptor method \label{Message-method-descriptor} The \texttt{descriptor} method retrieves the descriptor of a message. See section~\ref{subsec-descriptor} for more information about message type descriptors. ```{r messagedescriptor} message <- new(tutorial.Person) message$descriptor() descriptor(message) ``` ### Message\$fileDescriptor method \label{Message-method-fileDescriptor} The \texttt{fileDescriptor} method retrieves the file descriptor of the descriptor associated with a message. See section~\ref{subsec-fileDescriptor} for more information about file descriptors. ```{r messagefiledesc} message <- new(tutorial.Person) message$fileDescriptor() fileDescriptor(message) ``` ## Message descriptors \label{subsec-descriptor} Message descriptors are represented in R with the \emph{Descriptor} S4 class. The class contains the slots \texttt{pointer} and \texttt{type} : \begin{table}[h] \centering \begin{tabular}{|cp{10cm}|} \hline \textbf{slot} & \textbf{description} \\ \hline \texttt{pointer} & external pointer to the \texttt{Descriptor} object of the C++ proto library. Documentation for the \texttt{Descriptor} class is available from the protocol buffer project page: \url{http://code.google.com/apis/protocolbuffers/docs/reference/cpp/google.protobuf.descriptor.html#Descriptor} \\ \hline \texttt{type} & fully qualified path of the message type. \\ \hline \end{tabular} \caption{\label{Descriptor-class-table}Description of slots for the \texttt{Descriptor} S4 class} \end{table} Similarly to messages, the \verb|$| operator can be used to extract information from the descriptor, or invoke pseudo-methods. Table~\ref{Descriptor-methods-table} describes the methods defined for the \texttt{Descriptor} class : \begin{table}[h] \centering \begin{small} \begin{tabular}{|ccp{8cm}|} \hline \textbf{Method} & \textbf{Section} & \textbf{Description} \\ \hline \hline \texttt{new} & \ref{Descriptor-method-new} & Creates a prototype of a message described by this descriptor.\\ \texttt{read} & \ref{Descriptor-method-read} & Reads a message from a file or binary connection.\\ \texttt{readASCII} & \ref{Descriptor-method-readASCII} & Read a message in ASCII format from a file or text connection.\\ \hline \texttt{name} & \ref{Descriptor-method-name} & Retrieve the name of the message type associated with this descriptor.\\ \texttt{as.character} & \ref{Descriptor-method-ascharacter} & character representation of a descriptor\\ \texttt{toString} & \ref{Descriptor-method-tostring} & character representation of a descriptor (same as \texttt{as.character}) \\ \texttt{as.list} & \ref{Descriptor-method-aslist} & return a named list of the field, enum, and nested descriptors included in this descriptor.\\ \texttt{asMessage} & \ref{Descriptor-method-asmessage} & return DescriptorProto message. \\ \hline \texttt{fileDescriptor} & \ref{Descriptor-method-filedescriptor} & Retrieve the file descriptor of this descriptor.\\ \texttt{containing\_type} & \ref{Descriptor-method-containingtype} & Retrieve the descriptor describing the message type containing this descriptor.\\ \texttt{field\_count} & \ref{Descriptor-method-fieldcount} & Return the number of fields in this descriptor.\\ \texttt{field} & \ref{Descriptor-method-field} & Return the descriptor for the specified field in this descriptor.\\ \texttt{nested\_type\_count} & \ref{Descriptor-method-nestedtypecount} & The number of nested types in this descriptor.\\ \texttt{nested\_type} & \ref{Descriptor-method-nestedtype} & Return the descriptor for the specified nested type in this descriptor.\\ \texttt{enum\_type\_count} & \ref{Descriptor-method-enumtypecount} & The number of enum types in this descriptor.\\ \texttt{enum\_type} & \ref{Descriptor-method-enumtype} & Return the descriptor for the specified enum type in this descriptor.\\ \hline \end{tabular} \end{small} \caption{\label{Descriptor-methods-table}Description of methods for the \texttt{Descriptor} S4 class} \end{table} ### Extracting descriptors The \verb|$| operator, when used on a descriptor object retrieves descriptors that are contained in the descriptor. This can be a field descriptor (see section~\ref{subsec-field-descriptor} ), an enum descriptor (see section~\ref{subsec-enum-descriptor}) or a descriptor for a nested type ```{r extractingdescriptors} # field descriptor tutorial.Person$email # enum descriptor tutorial.Person$PhoneType # nested type descriptor tutorial.Person$PhoneNumber # same as tutorial.Person.PhoneNumber ``` ### The new method \label{Descriptor-method-new} The \texttt{new} method creates a prototype of a message described by the descriptor. ```{r newmethod} tutorial.Person$new() new(tutorial.Person) ``` Passing additional arguments to the method allows directly setting the fields of the message at construction time. ```{r newmethod2} tutorial.Person$new(email = "foo@bar.com") # same as update(tutorial.Person$new(), email = "foo@bar.com") ``` ### The read method \label{Descriptor-method-read} The \texttt{read} method is used to read a message from a file or a binary connection. ```{r readmethod} # start by serializing a message message <- new(tutorial.Person.PhoneNumber, type = "HOME", number = "+33(0)....") tf <- tempfile() serialize(message, tf) # now read back the message m <- tutorial.Person.PhoneNumber$read(tf) cat(as.character(m)) m <- read( tutorial.Person.PhoneNumber, tf) cat(as.character(m)) ``` ### The readASCII method \label{Descriptor-method-readASCII} The \texttt{readASCII} method is used to read a message from a text file or a character vector. ```{r readasciimethod} # start by generating the ASCII representation of a message text <- as.character(new(tutorial.Person, id=1, name="Murray")) text # Then read the ascii representation in as a new message object. msg <- tutorial.Person$readASCII(text) ``` ### The toString method \label{Descriptor-method-tostring} \texttt{toString} currently is an alias to the \texttt{as.character} function. ### The as.character method \label{Descriptor-method-ascharacter} \texttt{as.character} prints the text representation of the descriptor as it would be specified in the \texttt{.proto} file. ```{r ascharactermethod} desc <- tutorial.Person cat(desc$toString()) cat(toString(desc)) cat(as.character(tutorial.Person)) ``` ### The as.list method \label{Descriptor-method-aslist} The \texttt{as.list} method returns a named list of the field, enum, and nested descriptors included in this descriptor. ```{r aslisttmethod} tutorial.Person$as.list() ``` ### The asMessage method \label{Descriptor-method-asmessage} The \texttt{asMessage} method returns a message of type \texttt{google.protobuf.DescriptorProto} of the Descriptor. ```{r asmessagemethod} tutorial.Person$asMessage() ``` ### The fileDescriptor method \label{Descriptor-method-filedescriptor} The \texttt{fileDescriptor} method retrieves the file descriptor of the descriptor. See section~\ref{subsec-fileDescriptor} for more information about file descriptors. ```{r asfiledescmethod} desc <- tutorial.Person desc$fileDescriptor() fileDescriptor(desc) ``` ### The name method \label{Descriptor-method-name} The \texttt{name} method can be used to retrieve the name of the message type associated with the descriptor. ```{r namemethod} # simple name tutorial.Person$name() # name including scope tutorial.Person$name(full = TRUE) ``` ### The containing_type method \label{Descriptor-method-containingtype} The \texttt{containing\_type} method retrieves the descriptor describing the message type containing this descriptor. ```{r containingtypemethod} tutorial.Person$containing_type() tutorial.Person$PhoneNumber$containing_type() ``` ### The field_count method \label{Descriptor-method-fieldcount} The \texttt{field\_count} method retrieves the number of fields in this descriptor. ```{r fieldcountmethod} tutorial.Person$field_count() ``` ### The field method \label{Descriptor-method-field} The \texttt{field} method returns the descriptor for the specified field in this descriptor. ```{r fieldmethod} tutorial.Person$field(1) ``` ### The nested_type_count method \label{Descriptor-method-nestedtypecount} The \texttt{nested\_type\_count} method returns the number of nested types in this descriptor. ```{r nestedtypecountmethod} tutorial.Person$nested_type_count() ``` ### The nested_type method \label{Descriptor-method-nestedtype} The \texttt{nested\_type} method returns the descriptor for the specified nested type in this descriptor. ```{r nestedtypemethod} tutorial.Person$nested_type(1) ``` ### The enum_type_count method \label{Descriptor-method-enumtypecount} The \texttt{enum\_type\_count} method returns the number of enum types in this descriptor. ```{r enumtypecountmethod} tutorial.Person$enum_type_count() ``` ### The enum_type method \label{Descriptor-method-enumtype} The \texttt{enum\_type} method returns the descriptor for the specified enum type in this descriptor. ```{r enumtypemethod} tutorial.Person$enum_type(1) ``` ## Field descriptors} \label{subsec-field-descriptor} The class \emph{FieldDescriptor} represents field descriptor in R. This is a wrapper S4 class around the \texttt{google::protobuf::FieldDescriptor} C++ class. Table~\ref{fielddescriptor-methods-table} describes the methods defined for the \texttt{FieldDescriptor} class. \begin{table}[h] \centering \begin{tabular}{|cp{10cm}|} \hline \textbf{slot} & \textbf{description} \\ \hline \texttt{pointer} & External pointer to the \texttt{FieldDescriptor} C++ variable \\ \hline \texttt{name} & simple name of the field \\ \hline \texttt{full\_name} & fully qualified name of the field \\ \hline \texttt{type} & name of the message type where the field is declared \\ \hline \end{tabular} \caption{\label{FieldDescriptor-class-table}Description of slots for the \texttt{FieldDescriptor} S4 class} \end{table} \begin{table}[h] \centering \begin{small} \begin{tabular}{|ccp{8cm}|} \hline \textbf{method} & \textbf{section} & \textbf{description} \\ \hline \hline \texttt{as.character} & \ref{fielddescriptor-method-ascharacter} & character representation of a descriptor\\ \texttt{toString} & \ref{fielddescriptor-method-tostring} & character representation of a descriptor (same as \texttt{as.character}) \\ \texttt{asMessage} & \ref{fielddescriptor-method-asmessage} & return FieldDescriptorProto message. \\ \texttt{name} & \ref{fielddescriptor-method-name} & Return the name of the field descriptor.\\ \texttt{fileDescriptor} & \ref{fielddescriptor-method-filedescriptor} & Return the fileDescriptor where this field is defined.\\ \texttt{containing\_type} & \ref{fielddescriptor-method-containingtype} & Return the containing descriptor of this field.\\ \texttt{is\_extension} & \ref{fielddescriptor-method-isextension} & Return TRUE if this field is an extension.\\ \texttt{number} & \ref{fielddescriptor-method-number} & Gets the declared tag number of the field.\\ \texttt{type} & \ref{fielddescriptor-method-type} & Gets the type of the field.\\ \texttt{cpp\_type} & \ref{fielddescriptor-method-cpptype} & Gets the C++ type of the field.\\ \texttt{label} & \ref{fielddescriptor-method-label} & Gets the label of a field (optional, required, or repeated).\\ \texttt{is\_repeated} & \ref{fielddescriptor-method-isrepeated} & Return TRUE if this field is repeated.\\ \texttt{is\_required} & \ref{fielddescriptor-method-isrequired} & Return TRUE if this field is required.\\ \texttt{is\_optional} & \ref{fielddescriptor-method-isoptional} & Return TRUE if this field is optional.\\ \texttt{has\_default\_value} & \ref{fielddescriptor-method-hasdefaultvalue} & Return TRUE if this field has a default value.\\ \texttt{default\_value} & \ref{fielddescriptor-method-defaultvalue} & Return the default value.\\ \texttt{message\_type} & \ref{fielddescriptor-method-messagetype} & Return the message type if this is a message type field.\\ \texttt{enum\_type} & \ref{fielddescriptor-method-enumtype} & Return the enum type if this is an enum type field.\\ \hline \end{tabular} \end{small} \caption{\label{fielddescriptor-methods-table}Description of methods for the \texttt{FieldDescriptor} S4 class} \end{table} ### The as.character method \label{fielddescriptor-method-ascharacter} The \texttt{as.character} method gives the debug string of the field descriptor. ```{r ascharactermethod2} cat(as.character(tutorial.Person$PhoneNumber)) ``` ### The toString method \label{fielddescriptor-method-tostring} \texttt{toString} is an alias of \texttt{as.character}. ```{r tostringmethod2} cat(tutorial.Person.PhoneNumber$toString()) ``` ### The asMessage method \label{fielddescriptor-method-asmessage} The \texttt{asMessage} method returns a message of type \texttt{google.protobuf.FieldDescriptorProto} of the FieldDescriptor. ```{r asmessagemethod2} tutorial.Person$id$asMessage() cat(as.character(tutorial.Person$id$asMessage())) ``` ### The name method \label{fielddescriptor-method-name} The \texttt{name} method can be used to retrieve the name of the field descriptor. ```{r namemethod2} # simple name. name(tutorial.Person$id) # name including scope. name(tutorial.Person$id, full=TRUE) ``` ### The fileDescriptor method \label{fielddescriptor-method-filedescriptor} The \texttt{fileDescriptor} method can be used to retrieve the file descriptor of the field descriptor. ```{r filedescriptormethod2} fileDescriptor(tutorial.Person$id) tutorial.Person$id$fileDescriptor() ``` ### The containing\_type method \label{fielddescriptor-method-containingtype} The \texttt{containing\_type} method can be used to retrieve the descriptor for the message type that contains this descriptor. ```{r containingtypemethod2} containing_type(tutorial.Person$id) tutorial.Person$id$containing_type() ``` ### The is_extension method \label{fielddescriptor-method-isextension} The \texttt{is\_extension} method returns TRUE if this field is an extension. ```{r isextensionsmethod2} is_extension( tutorial.Person$id ) tutorial.Person$id$is_extension() ``` ### The number method \label{fielddescriptor-method-number} The \texttt{number} method returns the declared tag number of this field. ```{r numbermethod2} number( tutorial.Person$id ) tutorial.Person$id$number() ``` ### The type method \label{fielddescriptor-method-type} The \texttt{type} method can be used to retrieve the type of the field descriptor. ```{r typemethod2} type( tutorial.Person$id ) tutorial.Person$id$type() ``` ### The cpp_type method \label{fielddescriptor-method-cpptype} The \texttt{cpp\_type} method can be used to retrieve the C++ type of the field descriptor. ```{r cpptypemethod2} cpp_type( tutorial.Person$id ) tutorial.Person$id$cpp_type() ``` ### The label method \label{fielddescriptor-method-label} Gets the label of a field (optional, required, or repeated). The \texttt{label} method returns the label of a field (optional, required, or repeated). By default it returns a number value, but the optional \texttt{as.string} argument can be provided to return a human readable string representation. ```{r labelmethod2} label(tutorial.Person$id) label(tutorial.Person$id, TRUE) tutorial.Person$id$label(TRUE) ``` ### The is_repeated method \label{fielddescriptor-method-isrepeated} The \texttt{is\_repeated} method returns TRUE if this field is repeated. ```{r isrepeatedmethod2} is_repeated( tutorial.Person$id ) tutorial.Person$id$is_repeated() ``` ### The is_required method \label{fielddescriptor-method-isrequired} The \texttt{is\_required} method returns TRUE if this field is required. ```{r isrequiredmethod2} is_required( tutorial.Person$id ) tutorial.Person$id$is_required() ``` ### The is_optional method \label{fielddescriptor-method-isoptional} The \texttt{is\_optional} method returns TRUE if this field is optional. ```{r isoptionalmethod2} is_optional(tutorial.Person$id) tutorial.Person$id$is_optional() ``` ### The has_default_value method \label{fielddescriptor-method-hasdefaultvalue} The \texttt{has\_default\_value} method returns TRUE if this field has a default value. ```{r hasdefaultvaluemethod2} has_default_value(tutorial.Person$PhoneNumber$type) has_default_value(tutorial.Person$PhoneNumber$number) ``` ### The default_value method \label{fielddescriptor-method-defaultvalue} The \texttt{default\_value} method returns the default value of a field. ```{r defaultvaluemethod2} default_value(tutorial.Person$PhoneNumber$type) default_value(tutorial.Person$PhoneNumber$number) ``` ### The message_type method \label{fielddescriptor-method-messagetype} The \texttt{message\_type} method returns the message type if this is a message type field. ```{r messagetypemethod2} message_type(tutorial.Person$phone) tutorial.Person$phone$message_type() ``` ### The enum_type method \label{fielddescriptor-method-enumtype} The \texttt{enum\_type} method returns the enum type if this is an enum type field. ```{r enumtypemethod2} enum_type(tutorial.Person$PhoneNumber$type) ``` ## Eenum descriptors \label{subsec-enum-descriptor} The class \emph{EnumDescriptor} is an R wrapper class around the C++ class \texttt{google::protobuf::EnumDescriptor}. Table~\ref{enumdescriptor-methods-table} describes the methods defined for the \texttt{EnumDescriptor} class. \begin{table}[h] \centering \begin{tabular}{|cp{10cm}|} \hline \textbf{slot} & \textbf{description} \\ \hline \texttt{pointer} & External pointer to the \texttt{EnumDescriptor} C++ variable \\ \hline \texttt{name} & simple name of the enum \\ \hline \texttt{full\_name} & fully qualified name of the enum \\ \hline \texttt{type} & name of the message type where the enum is declared \\ \hline \end{tabular} \caption{\label{EnumDescriptor-class-table}Description of slots for the \texttt{EnumDescriptor} S4 class} \end{table} \begin{table}[h] \centering \begin{small} \begin{tabular}{|ccp{8cm}|} \hline \textbf{method} & \textbf{section} & \textbf{description} \\ \hline \hline \texttt{as.list} & \ref{enumdescriptor-method-aslist} & return a named integer vector with the values of the enum and their names.\\ \texttt{as.character} & \ref{enumdescriptor-method-ascharacter} & character representation of a descriptor\\ \texttt{toString} & \ref{enumdescriptor-method-tostring} & character representation of a descriptor (same as \texttt{as.character}) \\ \texttt{asMessage} & \ref{enumdescriptor-method-asmessage} & return EnumDescriptorProto message. \\ \texttt{name} & \ref{enumdescriptor-method-name} & Return the name of the enum descriptor.\\ \texttt{fileDescriptor} & \ref{enumdescriptor-method-filedescriptor} & Return the fileDescriptor where this field is defined.\\ \texttt{containing\_type} & \ref{enumdescriptor-method-containingtype} & Return the containing descriptor of this field.\\ \texttt{length} & \ref{enumdescriptor-method-length} & Return the number of constants in this enum.\\ \texttt{has} & \ref{enumdescriptor-method-has} & Return TRUE if this enum contains the specified named constant string.\\ \texttt{value\_count} & \ref{enumdescriptor-method-valuecount} & Return the number of constants in this enum (same as \texttt{length}).\\ \texttt{value} & \ref{enumdescriptor-method-value} & Return the EnumValueDescriptor of an enum value of specified index, name, or number.\\ \hline \end{tabular} \end{small} \caption{\label{enumdescriptor-methods-table}Description of methods for the \texttt{EnumDescriptor} S4 class} \end{table} ### Extracting descriptors The \verb|$| operator, when used on a EnumDescriptor object retrieves EnumValueDescriptors that are contained in the descriptor. ```{r extractingdescriptors2} tutorial.Person$PhoneType$WORK name(tutorial.Person$PhoneType$value(number=2)) ``` ### The as.list method \label{enumdescriptor-method-aslist} The \texttt{as.list} method creates a named R integer vector that captures the values of the enum and their names. ```{r aslistmethod3} as.list(tutorial.Person$PhoneType) ``` ### The as.character method \label{enumdescriptor-method-ascharacter} The \texttt{as.character} method gives the debug string of the enum type. ```{r ascharactermethod3} cat(as.character(tutorial.Person$PhoneType )) ``` ### The toString method \label{enumdescriptor-method-tostring} The \texttt{toString} method gives the debug string of the enum type. ```{ tostringmethod3} cat(toString(tutorial.Person$PhoneType)) ``` ### The asMessage method \label{enumdescriptor-method-asmessage} The \texttt{asMessage} method returns a message of type \texttt{google.protobuf.EnumDescriptorProto} of the EnumDescriptor. ```{r asmessagemethod3} tutorial.Person$PhoneType$asMessage() cat(as.character(tutorial.Person$PhoneType$asMessage())) ``` ### The name method \label{enumdescriptor-method-name} The \texttt{name} method can be used to retrieve the name of the enum descriptor. ```{r namemethod3} # simple name. name( tutorial.Person$PhoneType ) # name including scope. name( tutorial.Person$PhoneType, full=TRUE ) ``` ### The fileDescriptor method \label{enumdescriptor-method-filedescriptor} The \texttt{fileDescriptor} method can be used to retrieve the file descriptor of the enum descriptor. ```{r filedescriptormethod3} fileDescriptor(tutorial.Person$PhoneType) tutorial.Person$PhoneType$fileDescriptor() ``` ### The containing_type method \label{enumdescriptor-method-containingtype} The \texttt{containing\_type} method can be used to retrieve the descriptor for the message type that contains this enum descriptor. ```{r containing_typemethod3} tutorial.Person$PhoneType$containing_type() ``` ### The length method \label{enumdescriptor-method-length} The \texttt{length} method returns the number of constants in this enum. ```{r lengthmethod3} length(tutorial.Person$PhoneType) tutorial.Person$PhoneType$length() ``` ### The has method \label{enumdescriptor-method-has} The \texttt{has} method returns TRUE if this enum contains the specified named constant string. ```{r hasmethod3} tutorial.Person$PhoneType$has("WORK") tutorial.Person$PhoneType$has("nonexistant") ``` ### The value_count method \label{enumdescriptor-method-valuecount} The \texttt{value\_count} method returns the number of constants in this enum. ```{r value_countmethod3} value_count(tutorial.Person$PhoneType) tutorial.Person$PhoneType$value_count() ``` ### The value method \label{enumdescriptor-method-value} The \texttt{value} method extracts an EnumValueDescriptor. Exactly one argument of 'index', 'number', or 'name' must be specified to identify which constant is desired. ```{r valuemethod3} tutorial.Person$PhoneType$value(1) tutorial.Person$PhoneType$value(name="HOME") tutorial.Person$PhoneType$value(number=1) ``` ## Enum value descriptors \label{subsec-EnumValueDescriptor} The class \emph{EnumValueDescriptor} is an R wrapper class around the C++ class \texttt{google::protobuf::EnumValueDescriptor}. Table~\ref{enumvaluedescriptor-methods-table} describes the methods defined for the \texttt{EnumValueDescriptor} class. \begin{table}[h] \centering \begin{tabular}{|cp{10cm}|} \hline \textbf{slot} & \textbf{description} \\ \hline \texttt{pointer} & External pointer to the \texttt{EnumValueDescriptor} C++ variable \\ \hline \texttt{name} & simple name of the enum value \\ \hline \texttt{full\_name} & fully qualified name of the enum value \\ \hline \end{tabular} \caption{\label{EnumValueDescriptor-class-table}Description of slots for the \texttt{EnumValueDescriptor} S4 class} \end{table} \begin{table}[h] \centering \begin{small} \begin{tabular}{|ccp{8cm}|} \hline \textbf{method} & \textbf{section} & \textbf{description} \\ \hline \hline \texttt{number} & \ref{enumvaluedescriptor-method-number} & return the number of this EnumValueDescriptor. \\ \texttt{name} & \ref{enumvaluedescriptor-method-name} & Return the name of the enum value descriptor.\\ \texttt{enum\_type} & \ref{enumvaluedescriptor-method-enumtype} & return the EnumDescriptor type of this EnumValueDescriptor. \\ \texttt{as.character} & \ref{enumvaluedescriptor-method-ascharacter} & character representation of a descriptor. \\ \texttt{toString} & \ref{enumvaluedescriptor-method-tostring} & character representation of a descriptor (same as \texttt{as.character}). \\ \texttt{asMessage} & \ref{enumvaluedescriptor-method-asmessage} & return EnumValueDescriptorProto message. \\ \hline \end{tabular} \end{small} \caption{\label{enumvaluedescriptor-methods-table}Description of methods for the \texttt{EnumValueDescriptor} S4 class} \end{table} ### The number method \label{enumvaluedescriptor-method-number} The \texttt{number} method can be used to retrieve the number of the enum value descriptor. ```{r numbermethod4} number(tutorial.Person$PhoneType$value(number=2)) ``` ### The name method \label{enumvaluedescriptor-method-name} The \texttt{name} method can be used to retrieve the name of the enum value descriptor. ```{r namemethod4} # simple name. name(tutorial.Person$PhoneType$value(number=2)) # name including scope. name(tutorial.Person$PhoneType$value(number=2), full=TRUE) ``` ### The enum_type method \label{enumvaluedescriptor-method-enumtype} The \texttt{enum\_type} method can be used to retrieve the EnumDescriptor of the enum value descriptor. ```{r enum_typemethod4} enum_type(tutorial.Person$PhoneType$value(number=2)) ``` ### The as.character method \label{enumvaluedescriptor-method-ascharacter} The \texttt{as.character} method gives the debug string of the enum value type. ```{r as.charactermethod4} cat(as.character(tutorial.Person$PhoneType$value(number=2))) ``` ### The toString method \label{enumvaluedescriptor-method-tostring} The \texttt{toString} method gives the debug string of the enum value type. ```{r tostringmethod4} cat(toString(tutorial.Person$PhoneType$value(number=2))) ``` ### The asMessage method \label{enumvaluedescriptor-method-asmessage} The \texttt{asMessage} method returns a message of type \texttt{google.protobuf.EnumValueDescriptorProto} of the EnumValueDescriptor. ```{r asmessagemethod4} tutorial.Person$PhoneType$value(number=2)$asMessage() cat(as.character(tutorial.Person$PhoneType$value(number=2)$asMessage())) ``` ## File descriptors \label{subsec-fileDescriptor} File descriptors describe a whole \texttt{.proto} file and are represented in R with the \emph{FileDescriptor} S4 class. The class contains the slots \texttt{pointer}, \texttt{filename}, and \texttt{package} : \begin{table}[h] \centering \begin{tabular}{|cp{10cm}|} \hline \textbf{slot} & \textbf{description} \\ \hline \texttt{pointer} & external pointer to the \texttt{FileDescriptor} object of the C++ proto library. Documentation for the \texttt{FileDescriptor} class is available from the protocol buffer project page: \url{http://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.descriptor.html#FileDescriptor} \\ \hline \texttt{filename} & fully qualified pathname of the \texttt{.proto} file.\\ \hline \texttt{package} & package name defined in this \texttt{.proto} file.\\ \hline \end{tabular} \caption{\label{FileDescriptor-class-table}Description of slots for the \texttt{FileDescriptor} S4 class} \end{table} Similarly to messages, the \verb|$| operator can be used to extract fields from the file descriptor (in this case, types defined in the file), or invoke pseudo-methods. Table~\ref{filedescriptor-methods-table} describes the methods defined for the \texttt{FileDescriptor} class. ```{r filedescriptorssubsection} f <- tutorial.Person$fileDescriptor() f f$Person ``` \begin{table}[h] \centering \begin{small} \begin{tabular}{|ccp{8cm}|} \hline \textbf{method} & \textbf{section} & \textbf{description} \\ \hline \hline \texttt{name} & \ref{filedescriptor-method-name} & Return the filename for this FileDescriptorProto.\\ \texttt{package} & \ref{filedescriptor-method-package} & Return the file-level package name specified in this FileDescriptorProto.\\ \texttt{as.character} & \ref{filedescriptor-method-ascharacter} & character representation of a descriptor. \\ \texttt{toString} & \ref{filedescriptor-method-tostring} & character representation of a descriptor (same as \texttt{as.character}). \\ \texttt{asMessage} & \ref{filedescriptor-method-asmessage} & return FileDescriptorProto message. \\ \texttt{as.list} & \ref{filedescriptor-method-aslist} & return named list of descriptors defined in this file descriptor.\\ \hline \end{tabular} \end{small} \caption{\label{filedescriptor-methods-table}Description of methods for the \texttt{FileDescriptor} S4 class} \end{table} ### The as.character method \label{filedescriptor-method-ascharacter} The \texttt{as.character} method gives the debug string of the file descriptor. ```{r as.charactermethod5} cat(as.character(fileDescriptor(tutorial.Person))) ``` ### The toString method \label{filedescriptor-method-tostring} \texttt{toString} is an alias of \texttt{as.character}. ```{r tostringmethod5} cat(fileDescriptor(tutorial.Person)$toString()) ``` ### The asMessage method \label{filedescriptor-method-asmessage} The \texttt{asMessage} method returns a protocol buffer message representation of the file descriptor. ```{r asmessagemethod5} asMessage(tutorial.Person$fileDescriptor()) cat(as.character(asMessage(tutorial.Person$fileDescriptor()))) ``` ### The as.list method \label{filedescriptor-method-aslist} The \texttt{as.list} method creates a named R list that contains the descriptors defined in this file descriptor. ```{r as.listmethod5} as.list(tutorial.Person$fileDescriptor()) ``` ### The name method \label{filedescriptor-method-name} The \texttt{name} method can be used to retrieve the file name associated with the file descriptor. The optional boolean argument can be specified if full pathnames are desired. ```{r namemethod5} name(tutorial.Person$fileDescriptor()) tutorial.Person$fileDescriptor()$name(TRUE) ``` ### The package method \label{filedescriptor-method-package} The \texttt{package} method can be used to retrieve the package scope associated with this file descriptor. ```{r packagemethod5} tutorial.Person$fileDescriptor()$package() ``` ## Service descriptors \label{subsec-ServiceDescriptor} Not fully implemented. Needs to be connected to a concrete RPC implementation. The Google Protocol Buffers C++ open-source library does not include an RPC implementation, but this can be connected easily to others. ### The method descriptors method \label{subsec-MethodDescriptor} Not fully implemented. Needs to be connected to a concrete RPC implementation. The Google Protocol Buffers C++ open-source library does not include an RPC implementation, but this can be connected easily to others. Now that Google [gRPC](https://grpc.io/) is released, this an obvious possibility. Contributions would be most welcome. # Utilities ## Ccoercing objects to messages The \texttt{asMessage} function uses the standard coercion mechanism of the \texttt{as} method, and so can be used as a shorthand : ```{r coerceobjectstomessage} # coerce a message type descriptor to a message asMessage(tutorial.Person) # coerce a enum descriptor asMessage(tutorial.Person.PhoneType) # coerce a field descriptor asMessage(tutorial.Person$email) # coerce a file descriptor asMessage(fileDescriptor(tutorial.Person)) ``` ## Completion The \texttt{RProtoBuf} package implements the \texttt{.DollarNames} S3 generic function (defined in the \texttt{utils} package) for all classes. Completion possibilities include pseudo method names for all classes, plus : \begin{itemize} \item field names for messages \item field names, enum types, nested types for message type descriptors \item names for enum descriptors \item names for top-level extensions \item message names for file descriptors \end{itemize} In the unlikely event that there is a user-defined field of exactly the same name as one of the pseudo methods, the user-defined field shall take precedence for completion purposes by design, since the method name can always be invoked directly. ## with and within The S3 generic \texttt{with} function is implemented for class \texttt{Message}, allowing to evaluate an R expression in an environment that allows to retrieve and set fields of a message simply using their names. ```{r withwithin message <- new(tutorial.Person, email = "foo```### The com" method with(message, { ## set the id field id <- 2 ## set the name field from the email field name <- gsub( "[@]", " ", email ) sprintf( "%d [%s] : %s", id, email, name ) }) ``` The difference between \texttt{with} and \texttt{within} is the value that is returned. For \texttt{with} returns the result of the R expression, for \texttt{within} the message is returned. In both cases, the message is modified because \texttt{RProtoBuf} works by reference. ## identical The \texttt{identical} method is implemented to compare two messages. ```{r identical} m1 <- new(tutorial.Person, email = "foo@bar.com", id = 2) m2 <- update(new(tutorial.Person) , email = "foo@bar.com", id = 2) identical(m1, m2) ``` The \verb|==| operator can be used as an alias to \texttt{identical}. ```{r equalforidentical} m1 == m2 m1 != m2 ``` Alternatively, the \texttt{all.equal} function can be used, allowing a tolerance when comparing \texttt{float} or \texttt{double} values. ## merge \texttt{merge} can be used to merge two messages of the same type. ```{r merge} m1 <- new(tutorial.Person, name = "foobar") m2 <- new(tutorial.Person, email = "foo@bar.com") m3 <- merge(m1, m2) cat(as.character(m3)) ``` ## P The \texttt{P} function is an alternative way to retrieve a message descriptor using its type name. It is not often used because of the lookup mechanism described in section~\ref{sec-lookup}. ```{r P} P("tutorial.Person") new(P("tutorial.Person")) # but we can do this instead tutorial.Person new(tutorial.Person) ``` # Advanced Features ## Extensions \label{sec-extensions} Extensions allow you to declare a range of field numbers in a message that are available for extension types. This allows others to declare new fields for a given message type possibly in their own \texttt{.proto} files without having to edit the original file. See \url{https://developers.google.com/protocol-buffers/docs/proto#extensions}. Notice that the last line of the \texttt{Person} message schema in \texttt{addressbook.proto} is the following line : ``` extensions 100 to 199; ``` This specifies that other users in other .proto files can use tag numbers between 100 and 199 for extension types of this message. ## Descriptor lookup \label{sec-lookup} The \texttt{RProtoBuf} package uses the user defined tables framework that is defined as part of the \texttt{RObjectTables} package available from the OmegaHat project. The feature allows \texttt{RProtoBuf} to install the special environment \emph{RProtoBuf:DescriptorPool} in the R search path. The environment is special in that, instead of being associated with a static hash table, it is dynamically queried by R as part of R's usual variable lookup. In other words, it means that when the R interpreter looks for a binding to a symbol (foo) in its search path, it asks to our package if it knows the binding "foo", this is then implemented by the \texttt{RProtoBuf} package by calling an internal method of the \texttt{protobuf} C++ library. ## 64-bit integer issues \label{sec:int64} R does not have native 64-bit integer support. Instead, R treats large integers as doubles which have limited precision. For example, it loses the ability to distinguish some distinct integers: ```{r 64bitex} 2^53 == (2^53 + 1) ``` Protocol Buffers are frequently used to pass data between different systems, however, and most other systems these days have support for 64-bit integers. To work around this, RProtoBuf allows users to get and set 64-bit integer types by treating them as characters when running on a platform with a 64-bit long long type available. ```{r 64bitex2, echo=FALSE} if (!exists("protobuf_unittest.TestAllTypes", "RProtoBuf:DescriptorPool")) { unittest.proto.file <- system.file("unitTests", "data", "unittest.proto", package="RProtoBuf") readProtoFiles(file=unittest.proto.file) } ``` If we try to set an int64 field in R to double values, we lose precision: ## Deprecated Feature: Protocol Buffer Groups \label{sec:groups} Groups are a deprecated feature that offered another way to nest information in message definitions. For example, the \texttt{TestAllTypes} message type in \texttt{unittest.proto} includes an OptionalGroup type: ```cpp optional group OptionalGroup = 16 { optional int32 a = 17; } ``` And although the feature is deprecated, it can be used with RProtoBuf: ```{r groupsfeature} test <- new(protobuf_unittest.TestAllTypes) test$optionalgroup$a <- 3 test$optionalgroup$a cat(as.character(test)) ``` Note that groups simply combine a nested message type and a field into a single declaration. The field type is OptionalGroup in this example, and the field name is converted to lower-case 'optionalgroup' so as not to conflict with the type name. Note that groups simply combine a nested message type and a field into a single declaration. The field type is OptionalGroup in this example, and the field name is converted to lower-case 'optionalgroup' so as not to conflict with the type name. # Other approaches Saptarshi Guha wrote another package that deals with integration of Protocol Buffer messages with R, taking a different angle: serializing any R object as a message, based on a single catch-all \texttt{proto} file. Saptarshi's package is available at \url{http://ml.stat.purdue.edu/rhipe/doc/html/ProtoBuffers.html}. Jeroen Ooms took a similar approach influenced by Saptarshi in his \texttt{RProtoBufUtils} package. Unlike Saptarshi's package, RProtoBufUtils depends on RProtoBuf for underlying message operations. This package is available at \url{https://github.com/jeroenooms/RProtoBufUtils}. # Plans for future releases Protocol Buffers have a mechanism for remote procedure calls (RPC) that is not yet used by \texttt{RProtoBuf}, but we may one day take advantage of this by writing a Protocol Buffer message R server, and client code as well, probably based on the functionality of the \texttt{Rserve} package. Now that Google [gRPC](https://grpc.io/) is released, this an obvious possibility. Contributions would be most welcome. Extensions have been implemented in RProtoBuf and have been extensively used and tested, but they are not currently described in this vignette. Additional examples and documentation are needed for extensions. # Acknowedgements Some of the design of the package is based on the design of the \texttt{rJava} package by Simon Urbanek (dispatch on `new`, S4 class structures using external pointers, etc). We would like to thank Simon for his indirect involvment on \texttt{RProtoBuf}. The user defined table mechanism, implemented by Duncan Temple Lang for the purpose of the \texttt{RObjectTables} package allowed the dynamic symbol lookup (see section~\ref{sec-lookup}). Many thanks to Duncan for this amazing feature. \renewcommand{\pnasbreak}{\begin{strip}\vskip0pt\end{strip}} \newpage RProtoBuf/inst/doc/RProtoBuf-quickref.R0000644000176200001440000000226313164671406017505 0ustar liggesusers## ----init, echo=FALSE------------------------- library("RProtoBuf") options("width"=48) ## ----readab, echo=FALSE, comment=""----------- ab.proto <- system.file("proto", "addressbook.proto", package = "RProtoBuf") writeLines(readLines(ab.proto)) ## ----readproto, eval=FALSE-------------------- # readProtoFiles("somefile.proto") # readProtoFiles(dir = somedir) # readProtoFiles(package = AnRPackage) ## ----createmsg-------------------------------- message <- new(tutorial.Person, id = 0, name = "Romain Francois", email = "francoisromain@free.fr") ## ----serialize-------------------------------- # to a file tf1 <- tempfile() message$serialize(tf1) # to a binary connection tf2 <- tempfile() con <- file(tf2, open = "wb") message$serialize(con) close(con) # retrieve the payload message$serialize(NULL) ## ----readbin, eval=FALSE---------------------- # # from a file # tutorial.Person$read(tf1) # # from a connection # con <- file(tf2, open = "rb") # tutorial.Person$read(con) # close(con) ## ----getset----------------------------------- email <- message$email message$id <- 2 message[["name"]] <- "Romain" id <- message[[2]] # tag number for 'id' RProtoBuf/inst/doc/RProtoBuf-quickref.pdf0000644000176200001440000043340213164671413020056 0ustar liggesusers%PDF-1.5 % 40 0 obj << /Length 3839 /Filter /FlateDecode >> stream x\sܶf&L">fMkIؖ惬Pw8y!yV6{w tx:~-b9?9.a ~^峓_\batvɧglo^ yȉBsI\PgO&=-y]N@"X@bg,#dzw7vF/}kQe1O\L7̏J}kg!HhQ|Oyy,(3\[ O.?5˜>bl)HFK; vѨMШ կĝ(#sBB(A< |0$7u$+GOL+!b9ޞ͟}@ xxƈ+ @chRfdo#7t4F2jQ= -g(Ǘ"3%~ Ix}^Nw^p*+|@_-/Mb\L98$Q㔲D{B@/|1REH(?߸'~#1d{ MS^O?q{4&W}|QJ=qpթS[,󪟒@ۏ)xQ0Y4usgXDtˀ^RD$ C_Ą(Hp.tedzt+/Iɫx+S MKЛ?br$#G^f%:a$2 ZY@L5R61r{ZHgs5fF (A<_ΕE_?.x_Qk/?B?Mґ_77Jr. pPdd~Ou咏 YmQ/xZkV_`QoRC $ R*!Ig5^<ðVtwUqq|cOU7a=cqEqWroT^Z&&fE,jQi$ai+_ot?dׂFpL Fu^`撧k8ոQa1"d#„D!3 %AM[8zfdM !,{O5]b =,$x8bnE1R.m!azABD9OaX}[0ҕaIjsh$!'4RiU "H<5jQUf{rk=x8X͌ܒHc$(~Bo/_JFH :fZh@' g)ZbȢCD?8!%4 J1xH &YlvCxaH{t$DڻVІF`n<8cE%hkGISr0,Op,;8ܘT%馴}܁Z'2;`r )ކ6.6|ľ& `/H9[4]( ,ӷ6ݡqVzd\F3C-k Jr厍P+ ǂ [9W v߇)-y_lA`łƀ-jlY]\ GX?fS5(FMr{۩OzCȳI <r} &9c7 tCpz]V%j=!ٺVز0ǩb=N|TX$ad8 ] ؇*CGc> Ίj Aiz6vG/U J^)"}d(kk m\nc 8X͵"C(O֚hq N} FӐIԃ6#_q"_g#RNADL,kB(87j7 ݩ|* w&B5 TSP>#GBf΀[v^Oo 7//1vԋ+0oMS'wč5e,q*zȦrs_Ni|h;nVwašhn'08Hho=k:J{vPk>M̌0uZ&5Tx3DaPOp|d65 :߁YKO`Q 4:@=hUǠmgjcDp;Px "ܶhKlhAy-,S8Fg`$88v݀>](߬da|wmt[oLr}6K߱?77;c8m Ⱥ b; aHݥSB|M>_mwՑPbmϭC9>T̟; `8LG<J|s'0a̹:yO>ʼn 0U>wA)La,NT(&dHm6]) []&X}@A$dMs+{n,59lVLwBH`puq%Wop=n;piM(ƽ7UbC<~5Q`Gӥ5:E ߙҢ6a/<d+2!a.(R1flo%5mG-PwajD"QpإjyyN}!\ߓfГ?xk`LiVB;,UTuhBi}jtCew9^e1~mNb:=7,N;o? \.խ<lk_`c@~ϰAVV_'%s=1&^<+ F]QD؋],Qu;Լ DK-Q~[l|!h 9x+s{lrg*߼l,uNJhΘp?P o1X(xC/9pW4R $Ê:a},X }yᎂb6,AV endstream endobj 62 0 obj << /Length1 1454 /Length2 3654 /Length3 0 /Length 4612 /Filter /FlateDecode >> stream xڝTy8FQCaƐlckcf0iZHP!JH*oxdey&Nл|o99羮<) K8E TDq>{@q9"4N+*) Q)T $aX^dh'8/on(@#hxd_#! h< 0^Xy xAH" EoTM>"}u~;`I/L|!Q/$XP!3ilK$g9FݽZ\ص`řrv&H,6o]mKzg㶧cI:Axd,-vqiۢ6a3^jB[|ghy>#b8 ń\cjhٓ9[ut(.3aTf2+;ȳj]qIs}ҙĆVmpF! VuWrǢf1GJsrW 9j=K&V&R撅Ĭ( O[[U{~Lˤ>|K7NWBy,xa55N;1JU|uX}vA>Kr+UC5i-8sj)R'R2c➿#"-N3XZ G`w*.=|׾;h =pLJ< ZP*|jZZOyY:CQ8yS%u´iFGwe/&)͝yG+ĮjE?trcO=H3A'cWNcd~Lb>vUuQirF9k[KXiA6fg\sj=DRp8Gf>cx5BƊdm:xq)'F뺕t@9 |`z6RsZRT(][kepR(wf*ߠLQ,_k^tM#2"YKDGKVCc1ӣ)l}?P88fNz|h;7 uUn)f+on)YZ/({9`OD 5'jfF*]5(1feS&I|p"ޗWXl6q| BSj TTRKW2h%i۳{_d%+y,LW|yXʇzе"MC3}OIO6nݜw-09*͖} sE\HK|KDh}Rk',FR~JPϔ*@W3[˺nTFߏRt.X/@ذm5oa >s4mNa^rG_D5=T09֍;vpTs8^>eY|-ܔְ+<~N'_ =ܷ|HhGa1b PfB9>|JBb_٫Ơ祤_ iHΎ˕Iyq >Hfϲd4ݲ',(b"gub7󣤇 .((~q1V[|5k֏U3 w ^LIhUn$MݥHaV51z2Я)<{%r$U?>7`s04u%>Cz2]2'Vh83}o"W`d:L<Ѷ!/&`w~KF=o|=U)e,ﳴ&qeꢑns_ tC`q7->rx\U/݋YZ?Ȇ u^KghKwkZLWQBz.ʍ^mič6DOΙUq80\zo8h(vmCǪ“ĮQYCMd7|eBT7{3֍kJN˨ɺ'3MD O[}5|46q1;@c3m#P~j9YQ-?J7nEتadž&[{o90>AR$ѮYc)/Mœ*TD(l:ߌJ_.u :haIO >ݰ ~E#bb`3#ybx&‘l+'N-#**RGO37pfpXJBšG ?<_u+_GG~YJՒ^Ojp~u =e/{%CO5 - ^6v7](|>9$jELhl+݆gX]jUJKf~3GshLXIm:-^}q㋄C' 9"EVi_wK}uғ~×ÒLr^ȴ6 2A{0RTO>?|Kw-0;N.2,WqO#ΗΞ9|+T}yu߭NAɚJ9!!|YUeG,/3YCalDo&8|Jy,f,AQD.Y(|zvoٕ̬xeZxmuB%''TlHY֓__ :ҡٜ͑dZr; Y;PV!aMC/OGIV\~h%O}zhT9{M5kS;Ndž-4Ϻ5z>i5Ig>Dik%NIayҘ?$`-Buqe/9g endstream endobj 64 0 obj << /Length1 1838 /Length2 21032 /Length3 0 /Length 22179 /Filter /FlateDecode >> stream xڴzct۶vfǬv:vұձTlffǶa6>ܳ7jTL>\sZUȈl lm2J6@&F:![+#3=##+,17 g`fd%;|(ncG}e7;c&_@HgPۘS}ڹ99BG'o!z ocں|6c3}+ @X$WSWdgg?\Ui"ʢcUZWecY<eD5E l40ڇ_ fv ...N@Gz[Sz;)._q1(Y p;/B8i/siJKmmm ? dOc#4;98!o7u!ۏ;Ӷwӷq6mC[9s+?/2G~Tdž/?E&.VG Z[)GmԖ6.6%4112Ss#';s{'cI1Gfj`] $O? agk0ѷ{\`=G'c/+`8F憎-1&E1pKߪY|ʿFc>lmF& @g+1?FVn0/ 5?D)_sٿj/G ژZ_"?3dѬ @_>41,?*_t?,AQAIAL柽򗍨)ll.62vC 6.;'G/Udg08 8 A: R ??<?\M @P6lY 77/ϲK6ٿLd]?:CoH@!+;#A7] am Z4zOAqџT`KŁ/Obl5fJKpN)R' Dz[oI1REVWϐY-$:(fhk% sw=F1|GJ&.k]ͅp)cjBsBu]D]q|D\ YDV7m׈{n9'!0< & YaZ(^?iUk+$K+vc(GI~H[RhzʉwuhAD'jms%3QqqH"٠aAo_? g<d@8.U栨1^6)X8 -՛au҇**>} >a1z$ 'EdwT`n L+*)fsA%z{<1cc) v/(4&)U䡒7Z/%Ѷe$.mpy pFz&ݠgzWf' j"G7_o#OҜFփ!@;}yX}͍ysCY *᝵~])qMLȀ^RR-"W<5q/!c;mݻUݣV$kV;#&VՄn-~yX (Ilb(̀7WZCEn& ,͒iYu^enpN~ Gš\˯(g&{/ˮ$r*L!T,,aG/R: W)˷#Bl ѷ& ߾.,*}(F[Ey5@}kُ0A 7vZ6"7/㦮I/&>Xg[OSpM"B#<fItPa_H_ot4zp(Qi(ƶ9jb1l4:iުq%j!ycѲ'lLnc'$B |OZQQd0L:k}i 2)]pHT3…L-7& G"e( J3biyj&ax5}yǜ7=nE TZtn(]$5gh%f zȡ^IS>dmFg"za i暂蝹?FBi6]?{!@p᳆>1"J--pm`hEjf%RD洘4vVaЍpTɓ5q"۴yV|J^lj;px״ ],ҡϋX8Z ʃw9|[֋+:'Sx˷U  ~2jm1K(bZ[ezneB*"wn]u\)(X)h[͙L'xpS JQSR=Fv9ޚ]n0]3dsX=/=sґKf߼q/vM(p*%CoP73%2..*xݶLj-OX(**d=ΏNr!&UK1ܡo o;vYL׈o6:}%m2)J|J""@F>ـ@[}kA&F#w^$'jˈ)d8HS~.qwt3\?T"Iu/c4 OWj -`!|j1WYC|Χ.qpj{ # tUk8ǘe[Jzb Q>nSJFG?yjFO`l8n#< 5Ǡ({MAQSQvA^m#OO71IhVdFI;9̎((reRP (%jɧp| سz]uo= e'd]qwdD_xbf%$g )xsI^.%~M,9WgfpSEL,<=Ln;n Z7{zR6M撒eSsz·G[t>Tn}_M/G}9B|NR yLDqhA}= K{?s߭woUKUx2#ԓ5g78<= Xm_Q_=loV% | q%4Ƥ\f=0TI80tȖ()Vl7ϱ`wLB%W $׼nGAsZ1F,YSF7#<,~_V[NuB^Ɣe$O+e_&ϖe? o$5Ul+1g`Սhk 衛֖<9>8X$:}_^qhQsM ?,ӮnU&=¥;vLּ%¹YC|3;caʊY恮!jQ\Vάy?굥}*9YfBF޹RH@6NsNus9KlO! S +5 _VU WY9}([se_ʄ0y<'M![w`An\HT0 P@KfvY5w1E_TD.5'g J]hN RII=ֈ-DcŢ>Pq{W^DW2ݼ(ŚAؽbv_ݳ֬BUsn",h٠b5zP@C-hZCu C5pU¥LAl{߁^]?Tmuf *&u vtz+/ܖ@.f'TRM{V)zn"n4RO8V,ёXwc| Ce_~0/`xQ{,Hhi6o]E씊)A!?KL6/榩0!VWFuٚ"ITiMŗ=˗;Qȃ¨T5r8CS+vH/ѤӮ5֨cV4DRyo2}țfKU‘UIH0fnemg6DgjR~9d0g&zZlO}t˶$[0GtOD@hJ^7M,GfdG~N, d/S767/NBV 52zRȅq cVf++a&coaӇʄP14&!2hLUцZ%\rZIjD[Į@CΗXJtc(yT*Im&335' {wقY6>䭨7wHYڱʂw,O=5Ff:ދ#Ӓ$NqK?zn3,EMQ hh9kC[|ɍb#Tw8>AY6b]WE1N߉ժӣ@68J'Faz%GZcu7ZPE;W@o{RѼYQ4* 1X++lq$J ϐD@H.s) Y8+C6IVjf8^QO_a-a/TJJ"imZ{ۍ×싕(e`v<԰}&(xԱ.3{ܩEBdNyمhs:Rp;9wndΆ 23pʷH"gS.(gixlr̀4ogbS?_[\+z"Ȯ\!T,&B;%~Ej 9-<z(exDj)eJ>xyȳU+vy2h9R!>t4m_#:O[И;jWGeIMP>ͯJ~ zq$)~uЉʰ*!)9^I$Cv9EO >Q\u[.iwX^]$_:M{w@|S%kݎ,&b _ =MjH&v#LB*?bFwQcB]`l(I/C-*{|4!bwIL1:3DE`^15>Ck&QuP djo2%6*RsŶF %[ 2=or[93m3ąNb'W_[kQݧ l702r 7^QMS3K - Hp+^E5b㖕nMm:!&  ӡ4WeBY"z, V4BĴiUcn^>_zgmHfE))ESG*#OuЬ7g+7ٻdڵ6 Wx{&1;-'3u?O*Ec:KA"8F&u,?e!Y!18D3D(RLc<{ 8g!MQ@'0dx\nDb1'ȟY*EU#:t@:rj9)6HFYɫfc&Tq\Jt0.)U -ˑCf|/ǰ {襤P,@Ph0/4x?rK~M-l/x4?@O06oah ! ?%&ħ]gOz"xGB]¶7Ebr* ч(sX %bITQH>z5|P= }+gU`P ?HsAmI:^gidja[?\wp?IlѲc㥲=u7J UEεv*xώ2W+5ptwwbB~%w=C$y쟓i=ͺ#+ȤC/ :gaK߹J;KmNv_ֆӯp}cՏEMb'ֽX ضњו^S̲3BPh y ^4Ro}f/ 6Z2M=A]>6' a6AntFŝyҎ$612/bCl)QÙ߼P@55ѡTT`)ŨWsY20Zms&KqdV9 d-JΰNRJKkZɓ~sOƘ1/-=(sSlґv Ոx{@kUzt%?ĩ~\dƧzQIk[ؐRݐQ'^]q'?:1R ǜ9KR{R jC%`gVZ<L .I\#AGBYx-z 8Lc)YXrdM'%ҟ5hp;Ҫ6+Cez2HK5 ""MŜU:Cn=(x+3 p"p_+玎E|5Jpq i%eoz| '}\IߠT]їpa0tT!0)!t)UrU@20PZoN-#t=tXҟ`QnI}>"uU=o;nN[&W2^dm_o#=?< r~ƯD!KBQs-6Y`47d zt78=4b(*hH=ĄOh|ooHǝ&i$ƬsME|ct* 2D&xFZz)=x'P)p`'YV*0vӮmsCCRښ:$s0IB@~pZ+.\SܖXFN=&_ec[,!gJdY'|18{ \W!e<Bnډdw@$NM'fk&Uvs {5+tٺOq+yXT,?E?ڏkGjLm(ow5@Ltj>0ݤ'~+mTFNcRRH!VO%^kkkPl)Z د^ UHsٜ$X3V^%{ukLf2nxtֲ ,H+nHJ Qd0lЛ@FBH7@lW1/UXc/Y%n8`|^C3y*-Oʹ^ %9$ǣ) , P *` P+dӿuXj ZXUޅ#D "ǧph_2fnj(.xpH͊ED߾䣿ǮWmٵ7T=4 B9UOJ\}9n6TA\ HyDˢincšAh(褉>+ %gbxK 5ؾUm;*mc'(ؼp˽a펢 3an!oKYpj ^f1@򫆎"[N}'6 Фg:fQWTpc3BƼo}ͳF͗MOSi^ٖǸz4q@ڧ;hsH;?:S ;`DXbc K;қh<"[~VΔjrzs]-3n 0jCPWl6θIH[Cb+C\s.t${DK;/08 zRyO%iΘ眽s+8Xb&>ZjV*h,A6׳pQHșiىY%8,Oȣrԅ*[wAtJTw@hmdWMtuXg<$s\ȗa`friN\ː}۰#TbщrnV|b]߭U~^S3Wlקxhw}N>=}?Sk,\Η{Y9 ZFK| S[S;UZ _ Fkka, M{Mx+خu$]J>O8Bkáa wUWWË!JB^x6[MW[UE5H6[A/ov)R*3/sZ!"!{ )L x9L5,7`Ӝ\*̮Gw}QG6}eeCkhܖQ`4OV|~@ kW^*!-+\4b@k,^ٙ| o<g8a&YfYo>n ͼAKvEԊ@N9QsҷY5C1o19Ȣq GݧॣjSYͪυ֘s:A%a^yy/ri r ;o<%d _A8\5P0#5=Vl&dT$?w0,zFibQ\-דo";rnFɕ年W2<=J3+;-Yx?.׾&0|1֘}EG- "Cqf J=S V@*1{=*Sa1ο0>33n>wQ^vYҘVXS/m LӨOsv J։-ۗwNDWb`!'zȘ#Ǝ: 6c-%:FĐwA&PNIVb|k {)\oG-ׄN`FfW?iIkP !}f8yD]'t^92|Z:, Q|r9c{0??ow&/H_ " AċK 2zS)wnO*-lyaq?.$(VW|!d[f'i"פkЊpGY "*񊺨5mRN/RV4"]Rf4)LhE 7< QE 8Ӷ)tccOVA@'c سww !z (DѵK ߱4xg@ZxC5 q24Caf8BMqXb̜￙ w <`htx< l*&qG"p5YʆXTZ /\ ,L-U~a3#@=y_F[bi* ^q'[QIvA.y[Kca+=g $?n[<E</6?a?W}IF-y6$K(ԁ"0HLw2{Ķ\,r j%*M;=lLnf/9Q TexZ; ne\SUhIY]bPЭcFQ^Rud{W LX\TbH`'%` Ja4K6T6uWUL?{kjI>O '=Tlt7iR*a3[pv(& qx(osOOFw 諼au#R rcx_+1]]p#I g61u d`m߫XҢ#A{(_xԃv>XY-̱߮U<\ןuI'SP9-9w)d~uџ~ Hdue?-KBο2=:MRTe"HY^]5E.\"GaxѮPp끽!a;G=\%eͦc꒖I"AT"x9G]#ѩNZ,u8+82jNL e1 K*׎rUEG>+JdƆ܄1A6(wɁsdhŒJcMH]$|sA5#͌qwrh/b㑫'>Yg8ܢ HnPç_rYjruyM˱FR,8)Ejb5شe䌻p&hϮkoqwfGae}݃hPzg f~BQOh*2 P,s2@]$n =²DZ{{b y)3'zBKZLY@R46 \NTR`ⴌ!ǓR%_r=MtUqѣ3{rp6@A-ðhʼn ʼ2:1>;H(abHHK@-ȴfjs)w$uMĎZ$#W}vs)6؎q|䖞kK\ \g),2QPI$K߈.S[7g4DTnp@UNUXqyRWoxiۋ?H-8LfU46(b'⧀>T4" n'+碑, ?M2;a43QPճ;#`lYvK%,gڿuLi+6Qy=xLo"Tv}T @8GZh^ 5L9Z`O;I굱6_djmdjRGlQîo?쳓g @pͦՉ}n˞"("1>O].OSz˿1F*h~'R-&"x?6Mͫ ('y3bqNpqR ֋q1'IiO]ٲ* ed[ri6dBdz-EDz)ֺ T~zߜU3wIJ(duMV qVU ؤhp{]Q-SITq>T؆N-g)N ;/p&I i ZogWAI7vМt݋u1e|U !Fc#nF}{^ Sg'nzpJoMz hW c.|kv4N$eˌ[DCtd| ?/8ݒ. E-yus?2g)>yCmƻ78Ek& OԬ" &(1 7 3-wR3I|q1q?d畞n֋#kb2lol XcO`h,Z~3)bkK5VEW(UwH(!*'B6 _i.o*¨iIH!i絺 jNQ_/޵,\~e)0¾j.'JQ"zK~o[d TY;uB~&%<^ qӜhĜ7*(4Jmw*ɬ&5E}|6?|F, ĤH} < ˝.E\MsV!n_TSnKK[ZГ؉|!z0tGBͲ]NEd)sy9\ϰ}eAJSɒqDp&tO_fﻅX 4S4e J#g:~g7'1CVU\;{EkD5{w~`̺EzM U5J˻sɨZTEéfFįأvK`SnK\ƶNTw]LGM^BB(24X=p(O PvvLҪњ6n\69bZZٹrɦ1@4Z@:ЦWKr `GF%)UL1ʺ掟G?d>fה ?dœKLk6G%b}r鳁%j3 m6)JcWNFznš1ߊѤ AfQ!-$} &rvA9qvg}_bzV&]d#&Mni:xn1$m2@*M<Ց%x 1TdvS]@ܕ;esۢw V2oIDyeUiNJEs\,nM3 -D(G:7M;SBv_F!io&t ;OJ[FO!ѫWaor'IɵPšAsG%&OOO_9@|AӮ> “-#7ER6R6n޽ʴߟa:>Y2dߌ/h]xa -bYsHغ ;/d򟬝p2ag[-3cb;'xήAN#{"4^j-!Þ?V?t6Zܨ9§HL5ftZ'^&W_pKc FYVETH2"ŇzDXS*`0a_B^`Ty"c/;a EP/R_J˯ڄ op8MØC}F=¼ASh>-z*m>[d'knw vJR*F%Xϴ-˅ T[_qf% h8 uEeskdU{m:cݯoX6$ǎi-OS^wκoݳ/槒TNw̎]H=a_4*v߶  ui]pRrqVB*vbVltn68rdK93 e1,8 S3su4/N{^G&jSb0MhpK\"E^\NN;+*vguP«L3|o[}DJ8b*-}Ly dsFQ7aQJ@qЧwE.GOTzC=tt3nib2 -{I;z-ܵ_V_ѣ -1]*ʆ_eP%h[z ގtDjgomZ1"[zD n@lXY< @ưǰ䤁n  FZ[|5<4GSd$Y*{cwek tBܴ"dV+,,H7vaĐ'R+ϲ|aQc@xxjto)]G@ 78-(`tQ&-7]ϜSHpCӘ!QP7aQD AP7I;j1݈x#M~dwHI =s{(X`0Nm{ɭЭofc̳Q|@}`+sBe\\[Id9T 4_1)ʠ,J,W>A߼q>8s dI*< &ejb :DYx\IL4K5./G8KjA2ԡ.Z&c)x}o5E0]^,4@QHО>3``'VM sL .!@c iƦ%!lۃ?Nrw =)oJJJ;\f0jk*gcbpc !Kş's3I[[v$$%J`7`]ݗxk+<8(il%Ӎy& #)߭}EfYkE_r>;Vs!F , k7~C6-hVZx盝WZ$!\d;6X_H0+V*8*TY^oYt5xP9, f9#z_{٥P"d8m ;*,i3* M"i훘3&qqH8+W:yBƑHuԢE.x;6Cuº)r'I\ub+*Fzku_h}w7=09^i!xѽo4 7 BE 7'|N`zoRBY^ 'ٕ| MojaˤMlFW#KflKM%`KJSlGBwaa ^_ Diz-)V7¤;M#@Ƙi2=%CUzղb;G[_hHTcc83qxO;žv T2Eƶj SmMtNROhxpWKeVumzI xbC{n0´LLy@eio7 ]{aŏ9<ʣRagjȠem [97|*1B&ڝbg/\#i(LQc4 endstream endobj 66 0 obj << /Length1 1874 /Length2 23079 /Length3 0 /Length 24249 /Filter /FlateDecode >> stream xڴeT[kp) ww݃ 4wx>}ŜKڣj%: (rtcdeb((*A n,b {  % (a00"P@` Pjx;Y4he9yXY>r32h1&`hcRd( WUde_e7n#w3'Ŋ4m\ ;ǫ 0@5_ : 9W_F)?>xkCr GkS׿cTT6n@GSGG7S7wW/Ђ_ ..P_@Of`o'fmA6nX3qSUT`T9GFEЇ:Ln^n{OTB`c|8kW䓰 mtі6nĬh ߜ :^{VY?Du9,M]6_WS O"Vnǘ e-AN 7hrjI+:iKv3u/,GBoE˺~̽=H4Z%wl\eGs;G+oCC0먉+)%hqqrL]\LX>1@r8,A.%7 Y/oTrMxXY>\-Y@6? 'lߐ#?Gf?Gf@?G!@.?G!CT>^KbIm7Vwsm,ܬhbg(y2rpr?fP?Bu/K zֿl3#$K)yjt䒠ֳzp% ɀ¥A9T >À`r0,Ժ UdI-&͐ŵ>2cb Ŝ.b8oOc;U:Au"hϲe/.^kk n CtK&r0NzkIUz? 3w6!M\ I{Nb%k_~#ݙU<@2Sҩot?ׂM+Ak'5!eNzui{/=V7`(\֟;Ot31MTmڇ &a 5vQЮZR/ 鏴9}!,l^7@ u"+HQ Uy6K!Vx# }b&g`rA` K}_w.6Я~% LI[+n1& PD&zrg$&4=Sfo*~n/&32v`"KZ=<楆ZB 4#1]DRp xo RbG|y4o-ʫ Hӊ!bu! M^!?Y8G[~ J#Sskƨ0װ >q /Gg?% շ۲ ٔ%_#ʢ'sz/~|24`}+)jrFբ6ur.V&V{P;%p AK^ZؗA.gkƜ`sRֺk*;>Y۸8"05wZfm\+?ܑ/VAǏP{JYSùvY*Tq%rxVT]{һMxsЬ0 pxв&j_u:>Oh2B$5Zo#D>@io|̃;bVv!da-İ:lEm(I?Q,θΔu|6n+(KysK:a0c/x+MѠu +i,hܐ?牥umX2hzgt`^:WGjCU LnϦ!x8qH̎3aieyLO/fY4ӛ'#찕q5lBi,\.$L%+?RSr}4-{rấ>CnDTC"*f>6 }|xs up֟4q҅>5y]Q"WSRAa.bF݀2U4d33h $4nH+ WQƲfKNǘ(n+0=|yrF?C?H4"2o@")${t) F b><yޱ0`ly|5;԰*)Y 䉃:{v ^}6 ci 5{kڎz==T q<;tmSK`(_*1х=?w#ڧ[s-j VZ_Kay~ w֒1av)]}y]#M Ra0`j[hX+o+խ$._q>2AXmIVz7]9>J)pb;#ݝ;Jr\!;,,q"oﲑ^h9xagsuĚoRO9QG(m3 C:Ċ4dͨznO] gXm8 鞝"Tx'kG!G/ј#ԙjP7c#f#} b}Bm$V:0NiqOٻㅼtb>fmT?j& -q7[*Zã&k 9\e>O%m4T̔ i\ztKMc[ \fs/tK-9?C&孯>2%V֛z؈_WԈ8Y/j)œ-/lrC5 `4!gޙ)\-Pa=f鍍Њ"3ׁױj؎BkI4Y`UYGNL2~hC/?Lݽ$W>sL*"wugӾYM@B4!{);be:X kxYAp"+YoH~9HՋT 3"QȲjj|vB0G|pKj^Bz\>SNEWwj4سQ&mδw`U% _\ "AJ22c M_9_n*1IApՆq@۷S_XX(oOUnoLNuՔ<('HXWKxӘ$nZ[IN|6Z8 Z[Eϣ}SA"p"esR2Vo-QgLnWC_ʃ!ۼa= ;Jg!9ѽ1ZC%r /T&8&xHv:\47lcjDU'$cQAT:__`{Fc:Rwa=5,B,r9U ;?ܔW'7VJ! ̬'Qѭ*R⅁6>ZP i'\g6]\ g?jo\TJ"5,ċfnۭ˔c^ជVλ7K8]xf{=Q ,潛MDq$EM<I_!sj8loCah$+RhMJ`"Z_ [> gј[UrY~XER ݨWt!\3`!O!)czBRZ[|qݹgvR?T'K@{:Wԙ1V FZ:|梛SY?&triH>?* ^t).f V7>;;_F:C\rBSݬ1 ASݽA /9.>0ksx&:a؞|&>Pa# :*v̡E;QpA1r.DIkܐfСMw0Z"wkǏ'%E/@EI (H)@';T"mC5zuTaoTU-]0*%TMC'n!qY}!jO+H#e] @B!G|k " Z+=ɶ-ƂPYJaWzÛlÊ-Nq =k(W8etX4FZHR`jrl\zH$ZؑZDD_3+VaO LEsqɐjChϵwӝ:/w٬Zؒ–>GgZ>řxc?Mbr@rUPfZݶlKx.NX<.Az܍hqR1$]kv"PP1T_iTWDZyᔐ<9Cq(A$iXOOH&,9UyVZLFdջj ] UƷ/' Blq'P(`ͥKpYQVd+%$cVJ`pyjE.:MŌZEu#+e( 0DDChMdJdsPB,G_sUy:Vg<*/o,pd'n} .Pq`zpK0eAkW`Nfgg&W(q}%Hӛ]SB ܲח/ ]|WC:aNzwCUomVh\ 7m9/켉8b^G%Qj9xC?;M~݈^ItJYYd!nę3歒{YsHhD*9~rEޛk> xGYKaޕݹH~OMK~>Vu~~qbE:pkBbdrm/@IA/9@ta3]Qz>%UqmE}u . y+4%nY7e cV3bD-樕fZ]¬eVICQ=K.= (rS~s鋰*u7Zy GAkGqߢ"yq. mU5E9QE^8 ~3tGBNL [|Rđ\3 ՄF%LN6_r1$?MPS\^$uY墬/5˺? A|Q͢cx.@ʴ04NƯ=2ޥq~qif(B$K)I¡6uZchd`ᗡX*GC3PQmRL^ܶ(zEXHk\&+XI=FF(^#1+$p)C{E|;grV_/j~t /ɟ+@P,\ >jYʕtA#zRB>QN>-GJKa _>#l>Hbm^ֆ!Y,R_.msuL>}/ZqJ玷Ka@4↭\!/=Hq7r*aX?3_~:4 y@VGN4MJ$=ϫ_ujZ)6|~$%I}jMJ QbJ1t5ȝ;cvs; )9\Lm<2fLķ*=MSIև  ayfUjEf>ї碻1QUeq |s);.q}p +}ph$(┵2arTڞ~ }M4*hEXeR wRWiJ}`/뉗G8,pC|iUBPkqRp=f^~+{ ]lç!lc`B2}fF.G$VR4$tNC rn+ܻ;\rq5uKM?9/b'h?zֿ7\+TR aE4F >w P"h?B$XѾX,c#RbbC kSl"7v15eHq"Zh+Ydvv8$:hΟFw?̩_˼u?o3J2{X;#jqg\0SHM3 v7Kek7 ?+ !r+޿"b:/ M& bHXyI.j1t1jw~ۘ1olб^)A!2ꈌc 5w?Wnݲ[uC+H䯿 7Ӎȯ& 63YFzф=զUV<d%@%0_NRDg:fSSgA| g;nT ꓒ960'm  'P  c7A٭f_~a@lcHkoe|+#k`潃G9)_jj6[WΝge0=. wgb< UQRV_h7@͹(ewH/='N]=1,7ŷyaz߱L^l,?^8m!Q=d4s7;%z-1s uԟ?15N%Gq́;T4 PG Dr[3КmɆV]L#J/A~تm-nkc]Gʻ75- &rVϵ,c{N|-IVv-c.r gc~2[Dž5mغMX#n] >a^CFȨ_dP*kQ%LgV H Akfe@)6,h(&deppŒvLdD&/1e{h }lϿ9OOIDQ|e5h**<2q-"--ng!17E{l /F#+ȁ<Ոɒ{roE韈 Y-nV)B_q1^xn3 A+34fh Y8u;yr g_Č*(xCG|(?_O[D =,-59k ,[2iuU(Pq/MP"ӐWW2Ry8I5%'{!ݞl[X]> ΜQ0lzЯŰҟr @QǖZr\&z^ ߌ+N 1юX6c{>O_+ {ey0 ێk:tn!8^W*"Mꏪއ#wSVO4}ҹ:>;m)qa-8# Q$keΊejl qw!1<WS^ $x8MH^$k8ÃͧSٲ5IP@;T H~'wڞUD/5TMڧ /159jV7/G~ Ľ;tC"`U~š@UP6PkʵY^2okQٴr Jp Po;TOd!AEu 3tjk&+$oDp:Dz5t(~ (ϔ#鿼<-`5& "CV#(,ءb{a^N s1FET(k'称? xλa]S*{iRoZ) M3Ab7o~DbQ~i{QD╊CvR{ݎN&%G3v&ɑҟI =FfNdX)ӈ?;J1nut+A)W~kgH ]Ehd5UG@[9*R=Q4K3tI$J<}bAmVݯ8FqދVGlӫ0j*2˜bs^+kO<])/7SKӖK 4O\^XP%-0p(\ԷI*1zM+Pe\s|![ :ADC^Ͷ~tk!ŘFD$7sώ;m֝s&NL-=igYY0|ZH!9X8\/.bP"0_1O dOM*寅;t㦊olD (ažw:{i^;tH>sV${@s-xGk4K&2?]"J;U>X'zLjVlrFJw/S~#oGG곅LUW7GmhS펈v`K7EhzESNR.;hx3UzƃL]mDl?7%ӎuo NúwJz_DwmMFj"~'1˥*{~U](Vl aBb@&e q$' Z/~x]KF c_A@j /fv_10nm8єGǒ R "bqRzW seW .j@S˛_3z2"Y38%sj Ё-L%|v.0q*R%2ZH^mb ˜ D5=m+=B$V+^?\@;ou )^G\? v%-~PGVȬ~FTYH{k(ٙAoG9zsCW7]N,Dw.B΃C}~:'5˥쨒]%Z%Iwl(cT8J=|,Bb_i[ʩi ݥ hVۭ4@Sz`u rD>w2w qm)A\)iл3h Y(kX\}u3E~"+75qї`FSvgWQ[ ?LCCy烧&2sj(|6w՘9Wt A<  Ds6?O=o< F@]m+l/^U%V¢jΪrEyyLqŹΔ2BT"vTN!״4il(_bGиب1a "Xx7Os ߢ{S;Ƀ?J1 |_sqm %rp0)XeJ?x$R_Ƕ/{h=YR9u&k!@8v/)\ QcKd+|dUcgB)a(4 }i(Tmw\O@K/Cp+w12ل8d" YlԝVE2tV^̴[-\~'/c]1d.;(3`+әsj)N:mBvrZI~pu"&Q#-}$j~/2RkG'ˏx1t//j | WiM"̮f';X3+C/뵮+PDZ8ÁahdD a5z (BW;VfLjNDa';x {V{(FkDnkˏ#%`~Vt` d_Zpr΋d^+0$a,"b "t9ˡ*('ԂMynr%8)[԰b-!϶Zz?+;[NB2V$Md-Ο1.'@X#^= oTKec9Lk}vO` 3,و2ґ-Պ~%竅Rv BC̕NRuN0ufg #\ ԩY<-K:>=3, `B`X:4˙@c6WGLPG)z'5B_d8ȌMy? 9LXUgzh S-ڛ@_z2 vނvT.qDSH>'ej+jK&UjкKTCUQ!gv3] ߦ݀`}Z沆};|c_ϵS2Q@0v?BB Ls7iuds&f^,cq6xm܀JN/Z٪p6H _ὅ*/uJ)M/P_"&DTtI|axP6JZvl W]aR cn +ϛ|A5eY񭒆{/ѫ``zQԖFdSU}>&9,` %CO;T{yY 쁏 YcbEro~i\5waTRB]0TCOjbKEG&q$oҜ-`|33/[+ɀٸ%~q3;l(YXx_0I:ID)ҭS@l a,eOKVVB&n4OaӗtхuK Z3n:W|:S_Ư.Hw40fhijGGȒ($Pj#~[쒆__mWPehLDlՈDC ZGh3xkonI]˔RJſ+)* rK?&[R_kl80<ie~ 콤 @>M{x4 Gq_h%.e5A` CgNu1+APc߹fܥgj[yf'h淼Y^$ t?~,գq;NYxzG;'`+%@d_W1u%J(W0H=5yr! +zGL 6ﷰ0.\ ӾQQ+dAo6XV\8ad;dY@ ' +Xr1#VBqn&՛=d]ʔ20fbjiۛh R7-pu$|i"j*A/'j׼@H6YXRqQ I%Re_%,ܰuloy\`ۇ5^}bk'GP?dQ8\`:md/WłS\wQWZbG51ķ[󳶆7_|fr-/+E3]3Mf{>`KD+F p)@ri}w&6P,E[?kSqxPWғiw99gYWSW$*wK΃f78)V{V#k\5EQ^ q[[<ȝmТ M_4G ?̜!1G!&Q7ZΝc'^jVR_!ybC؍#ɇQAcUN^':LՐ@QG5a-"8J5K:dθss^ wYH'\;'}h#D[I90IS]Y Dva|7fh}HuŞ>|!B<5^B}٘xi837K=,lr9,PbQ$wVR"Q#d@_9h'}'3Q[mq$tlQE]NBR.3a1(Bo2{-ۧ&BEE1c⻩ =@Dnp+Il-w(\%{LĠIDG07|?o(2s(0P#yn 3y 1SzX{]%iU\dz#"9ɖ2,sًҗL>!U=gqJx˃X1s/h/j~o 8]1GUP2D]ڔ,9^>VaеX=ӣx\f~|_+`{D8H]/S[=r%)sb Iu(ݣzV!_j|j6i%ϟ[IsӤ*ƻ uۺ=l{Mo"Y ȥ^if(3ɸ^ce+Н A#0t_#RF ]%w~*O,+}6N m_AΠVQw-p1Z؆b?8Y%"w 0DXzǡ8t%ۻ:T *Ә0W3̪`8ُ/ 6Ơ5vwKNm6:i vic r9}1[h q94Co|HKԀ?A`).BfLW?MDkr Lfc`@0 sq]ZaϪkxSW m2A gϪ0 \Yg©wivǓ>1iK,=|Oum}w 21>i JH(ށ\EIpع=&Pq+uelJ ;OQ.7]K Y5rաU Jo8BĠbeP˛_U{zOfNaLw3]Ssr889LwwwÑ15S纯j[}g۠a=mI(46O35&|2+S>Fl+ctX̱ko'A!X.YxE'ʑb@0bhFG(Ls^yFy' hX7@f.S%IWU. ]nN$gx+uGw K?ji-I{&p4TS}w /`dv]c{le> 3>5stic6Eȁu}V 5 аS :h1%lCjjeOBKY ʕFG?nqz 2,ML#xjLT()ah:/Sd}\8U zeۣNۭ$m"Ԫu2g-oYcca }=`[B kiC\K=L#='fq{q˂Æ_Y/FK,! |q5v xWtGUEZDB<N fᶰl]<,J|<Ź2BA\DoM@JqRC S򣗯s %N4 ~)A v 0cڧp$I涱OC,sF$9qЫ=󀃶0K|7a#V/?)#߃hO808 g|D9؋AOāʼnյ/*_?sԐ]?KGkk\]%(P?˴3HGҵK-i^vd#dWn(SXB``+̐!AahS&iɯSB!zTCLR /xRԸzӶImWsշz:|#K{y[έ5:dgn#22/V`QLWRoIl֓4?ꄬ33í !&] † YD`xKH*AU_ӏE)%,lzf)sx`4I#nKa]3"#1 r8 Λ QI{|ऄ'H?7,{O?U>(C**ؼf!Z: :S1`b!r2S<9h8Sm5MRD«iҥhpZf鿯˼47lKQmrߝ,z0f1x_n|ݫUXT!Vdc8QJuz9UdVqhw/JUVHN.=e0 Ǘ >aJ&4g*i̾!ClOUiz:X+-=ǥBdVh5LvEP{1PwAE]LW >5HCxش;t ބc߿*|ع'V+7 u!ZKD peL=)eE-?5iBAJ_@{Q U}&k;EMY} !Ьw>|ĩ%Ejdd~XI9؏IȬu'XӞ@KH [D񗡤*IWm8fvJ\7̠ίӓ(#YFr/.k뇚+Zadg:xei0zG.wgi얙YK'c fOPCy?<ͼIm ]LqazhQ㲒)!c1!_VG\yp`Ju-fp gW;`eXKhR ~.*<(P1G6<{g?T$^C( YLXEf646&k\^Zd/8%RgQ0<7]  nĚ'0y prqEdCu|sJ.MUR^!k(V-kB2hJ/,>vMx'Ẅpq&!`AK) ] "WB@8V,b$=w4l,'T4:oQO9m|l>/p\k!Ɣd -x1Qg_D {ߜSkT ^X;bv bO\!Ka]o.sVt9ۢoOi)p\.o$r`gEqE{QB+e۷+5J[_%{lw8Az[Bw,'0^XqF4 9lmHE/*\A$6AGԓN@hK;8z0b>޽6r!ӌ-喩<"q _E9c9,MĊ|'J0c:ȏ9H9G9rzY_`Ǹ|;(tשI#a2m%'v1iKp"^L# HnJR?Hx?+ԇ2D3%&H< &/2OY#3;bIK*d#3Mu.Jɯfs`a8Kuamd@dq7{.*ҭ3}ZNJIqVEVǵvKwUz<}(FsotZ-NjD'8ֻռKCT2gAq*G4٥ir5~5N.䐋̀g!5Zy: .yMuWyve:/~4 H'p 1⠦.=J46,֒v @:\,#`, T[0 πA3F;b4aO|OouI(j^n,ҽ=}٪".%zH .9JIT'/U+SE\: b6uhoOSm]F ⿞?MЪΧZ]Fއ[(N)%^j門DW7sAd* @/DT_伥a%4FJ5yBw,糤.IpX7$>Z3"巬]Yu*I"Tm[5̚ș } ]D+-,iA9R7Qc}4,Uc c;!2Rl *_bPC*i(Ĭ&Yx\GfhWgz<}J"qOJb;NysʵSw롔+jrKOD߆܈fu9^эk{M݄Y\;6nGAN1<֔\mF32 ;C|$H` 9eqm,^o].7RVk(h\|"iфC?\<&ilbv3R(Ep,xBHy(~iTsr,#jvYKsZ|o)nbW'/m`p_[¾mT:|ppQ37HL>\ C0nAYa&4wT{-TBw=N*fju~gm'xE-&+hɠ$s:tGg8-i-&y]B" 0l`i[ Q_鲶#ļWDsrXtݻ AzL&tĤW ꁙ βzrOcG5u4:;^NIJMue4BGp%NNMjT!1jAko4VmKO/-J'URYǓb~U馼,϶2r)TUQ˸hsUܨdt<|$2 Zp{4Q) #%s _ƒ%==ۛY]J·s{/Nm2m}hƨ%Ak9I@-+HyJϬ8GROxB'UP8*sfmCưiژr18eg{R;_9l;ʰ!jTjf&\d3,})yiuitpȽYZg. +"p=p_"h}LD5"mQ;xLL!Em!;Ǜx'uqKetnEm8~Ζf6AIQ\ooCtsî8;;aezG\ubمOs>lW:aŠXU,):˜&a $q=2| w2h lQS{*mjoHp$'!nnMt|[4X%d.'98; 2?O??C8rD(>MOs-A:AQVwf[K1>zF9)Nfė~t<(4E{ZPͻw![I?ź15{~vH43ĔqZN8Oxm/S|L ɋ;K0D:!R?|&=8o։+?`ݻ_/U{(phkgsþ=оsUr ҃h˞]('o 4#eEJ+Ns1|$/f~b$:MzMJ ^@\ӔcM?Pےkaoj7=P:i1@-BE±4ꏅ}g ?A_zh8k "5Ln YNXuG^K2|w@>:&4LJZW(eF o&_ڒ~2[[FmK_R!XkԮdvs]U3\C wZ>ff~F⎼υi/nhhiقy2w'6$byZɜ&yGҲ~Gאݭ(n. m- 2xϠfǒ~\=au^)+k+'&ȼԶ%y~FjwhRH rFt |U:Ә*ӵPV&eFNGDioK>A#.pV- Ӎ D1$␜.JwC"{Sh0ZNޘ~+RVm7@.ARo8~ fr6\fVd-9&#ՂLάF4=47b@֯AbTy#3&j=z7)f.X亽+MIM*mvW^oٶ\+-#F> stream xڴuTK;%hCpwwwи{pww$;fy߷XM]NXMJL+hlkqecr*M Lt ,p@'s['  o G >Cw,@0 (::8~66@ʏa[;wsS3?9iid-D20uu4dr9`432ؚTUeQ%e2%Gbeg;;["*NSh*m>T>|8 UTTe#hh#P[G_fNNv\tΎNttvVS13w:X>VlcN'3'H_FV~}N?9p_2 2ks'ч#@/4&@ @O S҅l?Vmm;f`lm01Qgmd$DUhe>φV;6tNnNy'("1&&&ǐ Z[v>>9:X[غxhsc?}7vW1wJ7g t0boO;[;#h898=io067rWvI[%6PuL)?Ψ;hG/g1%le%g` ?AG)݀ NFf_ ژZ?v/JIُkϭedf4Yl=#@/'#&H򗗨) ``1LOƏi65%z:[7NP!vf^oW}x*q Fzÿ'?#? #Q? ?ۙm~(2~3Gmvg3&NkCt`nʘ?;~\)T:~uHUŸ~oc1*?_S%P!Y's 'O:UKBBn,J`ga,j+K4o@nyֈ;"1G`OC*b9}[$w_AVh+#oSAaђX5yc(k#ITp4GN5 CvɯH*'_e&5:z,4rL]޺Z4؄`궄Ӂ4i#L59*e ty $+V$NT 'ʕr>&53Sh,>a@(V@3\40AY2 *FW5zwtnבTk>s YN,`[V4f`Dމ1<_SLsr)$x2UMB$^~Y*Z 9Q)xT,4BՀ$@خ*v9s>7/߆J2{)gG_(>x@DCZɗbQ%-Y Hh]]MnU9V7pc!_dl`;[wXx"q3Mبe)Xb  p6®H,l~De_MӲMƧ B%mnWiX_;7BT x.;E~Fbh2RYhDD\M`n)eoN;?( \r2q=d g)N\re8a~We$-'*?J=lc3 kKdmLCPhz*`+ b }iU&1#xr&$C-Ux:w[7MՋZ J^͹5&4o\ky](c}ђ7N魠pEŒ}Bg lKu0|qhf4/ ^֪/ tI߉L0lJx q1M#",YsN$ Ӣ<[[|K;FCq}RSҬ} 1hwejHOK^q(lZ䍵\Ub2ȌoʢGXm @ v 置kWQ` oBw+c],՘0JN\EoޓǟۢVK3 Kڿ-##^:kz:4V3z;$rWxc^'\Z>8_(u|3Ud̗Z6pGTrmM7PB[^?+JU/2G'˜VTAa #~&4 /+Ǝ@$/ Q҂4-Gs@aBY V[KS( tqde1͹)_8P`-6s_^&s)KI!RKSΤX(P@Gꃼ~cJkプo6-xUkr `~۵ZŌT#Q{̽⟄~_u2 MF'ZK8vU$?o uau<*rMsnVpj`,6׷6som?,oN9wbk&8ZJ[X.˦:&x}[ #(p;4S_QeE~3/VW+" ,?P&O%0m7 o!?V0Ν_eae 昊Kz7KVϽ Ֆ8xќ6d[z+49is%ObYmǦ5vIݰ&T7\Q?? T]ݛexɘV6wڮ N*`+aD /A'oؽPɴ89_ا_(^"% Sm[P'P0zCŎWddHwݽ6GVLȅ+aQ},,qoƷYb+\,۞?9KZjL͇i?RˬTwU`YìA$# $tEs%jnbŒ3Gb7|fS?3Zgz3= ^T}H}cu 6 zM~ mhwm5"Xޮ/cVOa<ݭG]˱F6ȥH/Wo,⤜@#CҜ;#81a&$)Rg$ުX3Pn4^ŤZV`PE( 'cb,sM97xB&mv܃ Q$F{.9D%|~R4" %O c',^wm[ :8 Bjh Plٔwguu'Mٝ, $ր\a&DO.b?KmP HC1NE~M>0Ch^#IPMZfVjDt RI(ժ‡/#}Ig ux./|RvbɅFЩZI_ 2L4)'["Cl6#ݳ`F'iȷS|cqm*_^K{-kZѧjS.cKJhJD{Z 5-5g%N;gM5'kC@`髿_!A\|.f]kZ&c o~]BpRHo˔Yƫ<({xBω [$8gX[-h|h&ŝ[On624Ys˄MVac@LLM ^=d 'kؖFRCHm-z 9z"ƨmrAYN0:D6Zl)şR̔ꛕ2=~k?&Ymrjy%-RAQgon9 jhyU)x C彾y|DdWU]96er4s#&KcCzP`Q"% P;V#Hm[5rFg"{̧_"KSYe9l'yikSmVIяH@` qid3J# 6?䡃<%WޟXa~J&y~3ܐŝYw.ũ:{xYEhLM}$je/Z0뻲A6]5[ʋvT]0 i EhiGt w;7[ 9A*A{:; P6ƁWl(pR@1C({n_PLqx>勉 !-9yۄ` d 3๺O)yKJwzthE <}߹)\ sz8T4t -M_6tQ !ZPifkL_}헻*& a;,r/``͆[Ae[2L)rጀɕIfLJnFzہeqY"в7YQ2Ч.{P$mn ًO 5lטyo2lk@щs_aüWtcOt#~lH5G%$(dEjEb?z_yf2iEkhOj=_u˩6[`fʺg_g'Br( n. gL X?MFW#`ݼPp+NFimD 6, 0lچY-AO+`U驻;9whzrs;&C45#PL2%%Յ~Cwx:.gſX>1jS1}mDd%Ӵ%o[ Ihbl뫫'FQ)mBL3JJ䗲,W;EgÝvAYUT"iYK5"vԶb14 gi!MLƷEe3X .m8gsGa8LQĩzEGk :#pل -cS-N'P&9t:7y\fϤ >2-WvhW}kv7BwM8=c& =[9lÓ`*GxiSP8Ui |')D\}*."tsTGŚ⣧ ]iF8J8^9{`e\"aLO $re3-ABճ&:ϤSEǦ55ѳe 9JSyαݥe  lqκD`L>fc 2*]hz'0qd_9-cyYd38x&P^JX(nY^mOr «@,(%}1d}>ΆZg=Ü&]&2z>?2X?5usps„ЅWVV۟DNI9%wFˎ->(B9B?TH5t_J^>ž3TҒ麵&RFƁLάU1K`18[kzŠ#j~r"{j Hx b3^I-rfMlKUw{Z6]I\̧#O4,]J&TL"_\AF&V)qn6P HķW[)̀Ț_j!c(,.ŋ(qMz4[BNuIVR, ,O+)ꕏ1oiȍ^Zw,0Bg@SQ:kc*fT~L~{eIv1!5l(~]ha:c ՟ ofYT!Ki_dAŴ/9bR%B#':2F%@P{"g?S8 WSd`P]&woR C!ض7`P sM3_ef-6=T<5-T oO -]lYMhfe)9CEx8I0Yc>c 2!ken!:O]~E'Zۺ'%+j~Ns| \L.2TɽmV؅"ۄKFm O}|NFp _0{qIVgZ%^⻺ZVѫ@zuTh6dj*G4؈9H^M*y"~ ϥ N7!1C~ ylJ\: $v^bq#[C1{nn~lY4.'1 sHh]A VyC|*Ҩ7<x3;{Y9wxhjpǞ(x `8S6La="\/ݴrSK7qٜTO.VV}[6T,ݔ)5;=KH]x]w{o0N^f2upo V̓/1. )#a$HN;? F`0j+[9oո.RRi' n/la r0ULS׼ l*SzMKY k##AVnP[ӊjLڲ/[-/{GÐki_bޤq ͝A_n*S&k ;_ܐh:drxfML)^6=Zߞ6|+ռ,NTA# ߞ2BTW6 ;XMr_ G^J-=N:0_m구'kql1D %8Ha0ƓgP\Q8GneS!@z%ݖ3"%]jw./ ~3>@uF9l.~p*~z"=B[D/٘D^7/}| @<ϑ]NP!s 2~WڃJ]2guWcvupUwW1a>|OpCBF/V@xƕ0dR)f^i/%>ӣM/_"@E6CRrbR4ǒ{2C#"2 бG՟;LjPO>]'VQ:z:qov TЩy>zfVSԤOλ{:-a{C)-35Y|!MǙ*zց8+=%3?'eqLۛ漹݊M*?7U6Eʀj{ӹkʲ$q/XB *$SX Ŀ}֌m3ÌGq!o@tY`L-ИCXmptB(}}IC4&ב Y5賍@ 6H\N^lwEolKY~4B4keJڰl8ZLD<\l︍,ЙSy.qV(Xw#rgPGr&pB}+(V,uʢ&krW6 G=tRj4e׻VGsG ɟܟ`S噀u% eʢ(Sr.:d[u.]uڜu0&3YFfq̫/)9n}{ph'H~X!Ƶk2<Ɯlj,{–| `~#b~nYJYBIFTLjZlfEuu< 9'tgǤ^4^#rdRX|j%Byâ=*`Q _uxMÓ5Xzt@ߩJ̣96٥v@6iЫvhVtp挌r}.QICD|bK܃g93Tf}ڬ0?`pPE6]$JN˜H G p|!6-=|:n{8BB}y(Jw%hc>&l뵜 >+m+<++ˏO7u?T)̥ͿHcO#e=%([@-ZԌM%j#,7Ƴ-fRU[wwa"\@k偂c_g 0uLIG5}#ʘ{{s$:'WKCBj"!QFzDkۈ=ɬ\ލg4DTC$ A7_氤k |ƓNtY(aD2h!mТsWRKBrk*g[, Fh$Kab gF5;D{Cm,  "%>`x3B*fzr4-t"$]Ja%-#hD~do-R W>^ cf~Rm2c`Li!ۿɱlCB.OAp5/$Һ !M^FJܡen"+d2xeCI|Ґ"ޅEb-)85W\SCLru &t7)&ìk3&t&H*PPO^JZ+1 C!} /lj)B'\f<8#yauZuN1 Q-;,eZ2Mw3w 81Ϝ[!?yd#jfk}JJ\iJGɗ<1նz!B YtbeigV.)ݏr$(`4nSSihF/a/h5UмUbp.e{ sMr '.:BlWn%HN.>gJ*4f*|u\%⹭Ɋ3@#C̦B {%BRbjp$[yRXA}ѥpηx_k 䙸rK1/IWHܴ,h[T : (P:Q<99 A GS ȇq&9n<07#uZR=yr|P쵻SG,8~15(N1~XsP+s^_,mel#)* YtGmR8V~BE S>C,2Q-B$#Y%X*z{,U~R3,`L3q<4&A~$^.de ,/y 2gb*OB2`W8y&)Y=W5>Iz hˢs."CScQ&le%BwvCCp~XQ7Ӟ슱&`vy=u ,uKMwX.d@c1WQo&3 Oձ' _+hˤ'6U i;\?uDE/7=Ԙo@Q-7*#kI98ؼ& L{jw[Sn˙0%s-tZE~](H}h׉Gqx+'l'$R-%-SoB\5\trVA\h>ȝaFZ@!Uڈiگ,syK̐q󋷻^bS!Q5Xb:͚duK ղ."lO(23+b ݃?S;t9r V\w3ҔGK~x|,KI <@hu-չqB+'nSʙ ˫q J%DVpt8,}5ZOy+狣}%ЮT&yywIXZl7%1o q #wmo\ԙr ~xڧCX 650 ӦS*UU2k)^66&\{]_2r 8O%d cRsI ~PMH,S~`EkyW̟)I$YGoX"09H_-_u.8_t56dOF1y ^[/CRd¿Oпn  2'TZ'qeW\;y]t5,pDL8Ж͢3^tmrQ / ##^[c-agoU5>Xz ZU}s^~zHad@!C@񢮸7or5߭Åkaj3K4N,k{U^<F߃-4YbsiDVs1/CҘ!״<cZ\ %C+`{xe^?w")wAzu⇶7"a+aц5LsrD;rXɡ-tEo{RһUb[sƕ]HnXBQ&>lJeO,!+CNNas=8F4P]’ӆ \ RubhBx1:pZVp:ߑC鰊x:܀دK-CuP=xe+,\Ŋ{ Ue2+&Цgkʒ{/tqZot 49.:c|l6jaijO{u)~qy8 cl9pGR0~| ,;o+C\87thҗW)G`xuR FCx/Q%,vl "6  8TvB{Vfoߘ׭mX>|ek-Z- 7| 3T,2˲i~1Lm9:^:d>7g<{0Y>pweqMɱ'癥{ʋ;XD( WFC+Ne!Ͷgv9C)xeq+}VzDl nSYHdW_ؘ T)&A;a7邃ut _8Qt* js+AD#)v3gKXf% zܩ*p9.c:9>o3m/lC)77+nћN,\~&XF+~I_c^KS|ʌ0ep6Z?uAt<dyD<-wǨZ_j -@aaFE`(*^S=Jokέ2T>lnFw+F b'h^֑0߾Y/ٱ(Jk;Kd"eL6I\XK5e9YVEv̨kq@-P_Ƶιm6KuJ =@ʿ_R1qJ2׿T:NB&P˕j5fh,}כSpdbwU$&55͜-/b *..\ С+V !Ɣ~dk3D)5Q7`yI0CfStk9ǟ՟'A`<#q]Y/V%vE5$ÁȲ5:emna_x:@`#'%&gאWGd 嵯x:#K-1R G`"}* rކA31nw5BLYRZľٜ`A`7PMЧt!Ra8sD?9"_dWc^'@:.bn9sYgMZ(ĽCUmcMJh8{(.!΅!N8zb<fϡf)jLc剠3VU#3P39qUF׍`T4#Pyr3HmW}T=様uC!O1}6TO*~qC>.J޵1*"(,O$7OnkޅO:cdҵQFqD4tTr^(AY& .|LǣGy%M ]j, quWS>7Y#j)=XUYb騨'7:C(~,L')O*9:5)Xj.4 nN+_ԔtَvU)~on8rz)7Ff֝m[JHC7Fniv8XS6R,7rDMRGy} O %ȹMBE%zzggÐM.-h "c=LiafəY`d^Q/ ''\+fMBꟑqg*˴r)_!Xde`;.s4ä]k" g6ؑq?.1F8UdO8f&:il]4}-$]rWM8`@ e&amHf}LNH\8" B @`v}oRH]L[a2TQ%.Ose C8c7skMa;!)@uXM?FZs +\7A2 @>L|; D|aN/̵O d?2KԱ8L I%eN$;Gܫp T!y~2 }"U&ܲh\lW"ݣpN?"/f$;*!2Q]3t XҸ(*[܉]&g2m.c?D\ M fl)6#ZnDqҠvݭ7QsVlK d$ Q'-`pVÏP.Źbt(y:±]3/ȬjafZ{7nӷFgmڞ! *19]y1 e.Rx]b+:?g[&̨G54kvQX ſ폳w^6a3 D(}\-s%G¯x%)'t~13>k8y9v\-uЎ|7alq_VQW`|@K<<NBm39"P]Ce)GRD.JoA{q8JR:VsKҳμ\0) ^Ē1$a+4k;Ή}>f "Nm]]Zt5 QMXhC N۽"mJaaj$.YCK',:B:s*̛;.}[[aSꈧ)o/6cڭGf ӊ>=<%_[@O@`W˸רn0)T(GӒlX3/-쫆3rdg4R~hXeQY)?:GbiJ]н `4ީP5&(<ռc7.dt\ypz jQMCQFG -ydPS{[Z,L|Ǎx D<"bfl9kX(#BFe h@4H&`սW69/+d0|XE/:g[qg4W(D&I+YGD;{=zcBs\޿Ař`exW6K[ wAE֏^_QTd>8Fwy+rC~c@7x|z3]hzXFeRz4p&%pel Z;Wc[Zɭ~kH3o[oJ=/U,ؐEi<jcí$]'b!MS [-' 8' I o\珟h LVrl]NvXxl(ڛp VBJv Hv3 q)ٝt[)B&l}$} D kK/'K\2`AWnې|j[!I 4h6ѫh뙳3-iR0%l nx%o͵]%N_j^ͨ)vyV!V%֛eN5cV~3HEڀx [#'L>p;b/VhLZ"+%op#./ްϔ΃Cn׵ĉ]ug,}-bU3%:$ O7$lٴ{r.љN]dz#^d*b[B4ybW˜ߏbgę~158`nO|gnj6Ï|xY-ic=t=E;.fw=%Ab_'zI~%<"dg̋—׬p75'OuIEc#`ׯl75c[Ĵ*k=]ܤ7+-@xf! Fau"LP af9,y"( & #*!g?|Q|WtEyeW>:SI{SW+;s0&Ʊ}ȵe,%<ÈQ ^UD'>̲{]`{81vW PPpޘݣҚ"znђz|g\KnaohÝBb5d]C<\ODn.rQ"x5(N]i}QQ$9u[YÝʄA͐1`Bsjsa?xr0߼"k{yɏ6 ɓvtUZ=4;?7&P?hJQBRm^^ ex8 D>Xc3a*`QO|:ʟtM.]e"{F~t!rv ɞnv3:p,g#ׁ7^>l̉ V7͢'T{@n_#%w8uFQ\#l'VP*vfuWI`T?uG^ASO8FS*CkXQ(AG#pI:4q{[zCuηk >oQ1@ _'I/672vФu}z "@zf kѰa!DnT+6nog5xÒ,&6BCl%m1 sC͊o}4p9Ur=T!rړ}""n7B`XLR?#)ٸӷ\v^`EK;@_u'!b y y?wjb5Mܥf'G(ԟE1z`OPL`)A7Ee[p (qħP. eJW"|%ԣ?i<ܢ~|r-.pjeEcuxL96J(J'yOwaLL¹JqD3'Aɀ32᝿p_e*:!ɰrQ DžHu٤CvWqtpk+k'c_L(w\We؃%P{lQJ.lguMLK##Qr]**IDTpܶ~67$g])fD3LJu9C{CNfMd۴_V%+"v w #L4FT2H$YU;nb | @Q@)s$?2NB_ *@t;RI`pJcх`|)-t#=}^8u'j׏3k ܧ*fzo4 _;XT@|r.vf=kEp!Shi[ ^@"_|ZgJP kqC$O1~w"dğ89BetSz-3-D5db?,i֔x@_Ñz-ibX2a:AAX:R5*hD<3$Wm?Vx 79y=Oe Vgkr\P vv;L1g~nw "k(F 9??'}% S#{ z4g )ѳ)Wf+{ AV@TQ躵ǰzDPҵYm@C ^VQU"I)߇DB [eKR?fQ_p |E HY֭(hNa0sj:Soq0Yt y7ttEc$p[ul=j,3KG'DVlF\r}[5h&4ª-:qX?xƃHyMe[ x}Tr9V5 !E4zY W'"Zh^l0t'}J~K'sVL&TQf+Pw hMz< }J B<8),I%ie!6D̳-Y+$,,ƿ1Ydz(b66}? wK|q QЙҼ{Ku0_:aqDNLDWū|1o Mx+^ZڵԄ c]ya0:/w@iNaxk)8t ħ=Q$T:wet|'36yN?{ϩٚ I /@R*'})JNZ* :PPRyiM(iz:1񝼾Cm䣍)OhB;wK 02{V ox&vDc5Ъ&`o+kmɰ}Q93R2E 'Y T+ˏ|ZḀF/D>͟[8&<ҺLǯggP'Om`^EwҝgHv,35d-5imՌ .ꙍ\|ZOwM 1)rWc>o.~x+|KUM5m `ΟXG[Xp$3 (Y3Nm+HmNc=͋$}#ep#Vn'zCSVQ4k_dvxNH}f&|b=eEdx9Kޫ5b6BL5+a..Kt`-_>":"r ߀$,,D$=0hӧw3}xt)v\{2i=I+˳v :gΕlCe |ڞ"H$lSܣ;XsMF*-&1e?z]fEdz̐\H]\) -LM7e^ VgnDnշ*cUܗY!;+{#j$vkw \Sng9Xi%k~rn/{O#T!V7 n+M nJQX&u Xkk#G01M'= 14~[kLj^{3ZRINhB0zD^O;76NڌnC;ݽ7D f!/ܒʅڳ We`FvoC`ʄ@ş? 5-HnEq5Y| moܣHH2B؎*FCTP}>ox LIquP-g="(0ٕSݨ RD[K$heŴ<|9Dc1Y{C)mq& Y ;MxB&3C]~r7b(5XgpL ]߾@%-uEG_W@cr74\6=yWvj endstream endobj 70 0 obj << /Length1 2748 /Length2 27170 /Length3 0 /Length 28775 /Filter /FlateDecode >> stream xڴeX5 "!AA;sӰMwwtw7 Hww#lsGy?kƘc͵J2e5F3 Pdfdeb+(A@ [c' "%l7`K) `aEHNE3@6Vph g03dhoae<,,s32;Z kljrsۛd 7 @-m s:@CMBU FIr715u )PS:߂Y];\AB]D][YwV+wFaC j vcfvsscpq3,lni p9 ?q7 +=[흁$AZH !;@4v'V^YY`gleۛB`g?6_b.NNk(ߒuQ3=[/c1c{gϿMAV`ḙl;3+l "2jgTAԱgOD\2<666 dH%@vvΈ9y0X؃?fs+{3ߺ80k[9e 1!Yt7d]Ymfmr:}́^Ʈ@#DVn)2搣Ov{s_f[sLi!g do0#2+qO-I[[Ec; (nvV;7SEY9KZ͔h/ 2"@Ȏc}l!# v~ZFV]L=Ѕ,YQ[YQR/ {S `d6NN+d̀L \>s06 qE ^7 Yb0KAf?S ?RO?ROS AiB q?2&Al&NƦ MYe˟? 4kb 6=|x%> 7i'{L-@Y&D;jft'rI0/Z~tj5=/ ًvBYe.]9D0"gâK qꡝ p &!8`S%U\B ĠfTR* Dмʂ("w5. ゎ8+CXuf`lSy:{#FVGa$yd|^1҅–-.4)ҳy@m~,&>hFYߎZ\^bԹQ(eAh38ΪO{d3mK`|ψ ;ٞFvSٽܩkzP~[(罪iDlֳJ-2]l'͛I==Jp|RozhZ),DJYB@x¿zaǏ)0xٰaO~ꛭxbJ720]{+/jFo @ ÃkJ 9'|ݒˍx8P:5ȗɺ? #.sHt@]G7ELE TW3 dC\!QK[w"PiY䅵>QA&fzM#eD? ԾA{.ڋ5a9c):`qc"#txmE?q2bԨy"H.-jbi0\!Kj-DMBku%pݐYVOSDKG4l{{_I'ofdž)dIToInE] (?tj*iaXύO|@F*͗w_gѷ&m8:R޸$x$i*Bm=#<* j}@G->?yoic7-%axMӝ^Qp1zh_dbßJ} 6ҭWXw:ڙ"#D  lxz7]=B 5z7R󚚰YvN穯}h븣j _sGĀg,tK$tCY6soLx.o my P5s'JG ʀk Yr9Ib QsgG^f;Ӧ+0kҽIJs?ݔ9=E]x(x}l=_P? ow| Oz| 34#% Xh3Bn"Opܜ>j+i]<䡟~ǝw]-J/t @B`YN;3Nxn Vx}ߖtg3Ea9z<r(U=BJy-*ث (cPdmJ%zV5iB4F%zϸư&T(*v1rbRhmݱ|V@02.DSp$> 0p{%uZhM:4{ _K/EF@-n5T431=N4jXx[V$Z`ˆ{1k ̏WvvoLK^ mt|zg?yF|f]8Um9h۾g.-AJĶ^H0|SF[]AiQz3nX T:}_:#PHyh(7SI_-D-;Avnd %ȬFDJyӎX1ӳ s><]WT`U1_-CFZ;Ӄ@JFYQyVZfngVx7xWU`x쇫~ڗWڋxl<@aKLfX6%ELyČ_VIZK:OU|"z~}ЂpXl`76|YT?|WRIjdzD}o5TJ(,LC`ޛ Z6Cea߬gO"47 CLO{3p|& 9ʦM_ ]־V9Ǚ|aJh4\>Ml/.@|Dyh['I K.?+qcc2@3rP2@-8^ItbEQis,BJ-aRy9M9.|sOM݅k~eODt?BC|f}""X >.I&EFgSXzJʑ9O|2|+W`[W-ZrMqZY~fM 8U XD=^EV5qbش=! a짪{ 3QEzҟةoLEӘ[~]|~{?bpEUSbSވ.e%=y}) .y(Mia*$Z71:j u>%IՁRZI<@@-ިJ㲻W~:o?̫]F(-Ԍe:iשcߢefӨ2nRC AI}f`Q|&-0ՖIFj Ϝ \XRNf Պht~پlH90wІ.sײIxH#UL ֶ196(5w| v͗ ёq ^]s\4><"N5.%)JL~j:E4lZaВ{ s+Զ*&M(a2wuoe)v`n#ZC `GLQ*+a@Hlچ<ƬI:.dٲTsRy˞n$%L#hR7{ElBw0\{w_~~tSLC[ GP Ȯ+E`(Qpig”gQЅo7~Tz_>bZp_%.؝ 5{.ОN lelr9\C޺OZfUb$2CIN eZZ:&Y<9–fggXU$tbF-1'C~f-O5z$ ۢ* ~(| [KA@m^3#(F/N6e{9 z#9u5X|4ڋ^ZB`3^p+[8[Fn(TqIe[ qy1 vY$z5&T)qW/S `2Cޘ*75xΘm:>-˽JP*Cׁ1u牚/28QG$[h9S7":u(~G~z\;>M̺;7||]<1wk(㇢o ;OnjB#8DOGH5)^!s>8p:V~G@ma&(3RާG夤FL4: M,N"bXOjVbu.WZ [7/{`!G * *ďyXRJi7UCe1R+dLTM">"sȊQNS]x͋iKQytĻ/S^'Jt?f<` g3+p? 7ZסHs9N{lHQ+eF#bKH.o_"+&Xk%dX lho*O .A3R@h≗*6rMI$Ԁq:vh&RcCel5 juJۤ6LO,M@(3Ce̼00\ncRx%bf(e#@.W<7N+#],_^‘{zZn޸ &LyK[!'Lԥ}<ʌGCMO_2OnN}l^rxb85ۢx"C7VGZͤ&f=Cz:HE ԖCTFX!$0&B.c R&Q"rȟ(";B 7+h8EnȠb)!׻VKDq̃j;-%֒g2b&sZ*0}3k TlJ?K{vzoYhOA",r\vSgiuAp#Ss:]"eW+֫2&oANw߅0Z΅tRwM,;MeHfS> t:~'Ayd[s>ת܅: V)>`]EMU@%^bau+kUoT=*s/u}5eN8z"%rbzQ(_. \[\X(MՖξnt"@aU>U?f{/ 'zGZ0. <ѭ`SQJ`Vu,< P *xypLu>haoGW|rl+e!nzf5AŘDUJIY ˜zz-{^~ )?$+zZJy\x3X]G@846#B5 ?pXRk2vd d{]tw)L6B*QjĹ$àA}ɀ =M)BZd'~aNay)5aE/hJڲq Rz4] U8ĦY5~UW!C{#B zәs@3 L,=W9aȈ~W {zVHO'YzM \"J}[toIPn^Pᢁ"̊ R 0nY2{Mʅl|hHcB(.:$9;8 p$:(Cy[emn(#&Xˑ*yǠ% hS[̳:z)ύH0guv#Hq,UcNuԻ0mew:0aZ*&p< tu-~C 9elJޒIcEڗM%-2_<8Qʥ>* 呐,̝>h8 QFgsq3F_+8[^;S5>օm/o+xɌ J'^8Q~{ ٦ }?`@pwKXP՚>'m4ϐyϼ%*^NwLZ^s_r&UD1Р^w!# `+ ]|,lѺ2LWLX}ф*QEYYO(hslW4DPk΢URBi/WnC;UuMKドn, pwsGP71?~qO=>Cq8 }?' hbKS C-tdNޜMeRF$]N&4d3+9-5oH[e cSzPH;^5l7LRm^JҢG6|s?e,ۃ/{ΙxtJQsAsP\l^v m̍QU @0ӥ-u<d!W, 3ڈ[a8u0w2+gqڧjʔ V %EX=SL$ ϳq%M[Wٺa\گ'9ai8G7YY*=z"byNm-RFWwhq?b]0\$N,h{B2;j5%!({EN'P/HGNb*I }acf2`[Y~*t0lJ=_^5YC0@ȵ&-} 5TMrD鱳Js :?M #?@<9=/&q4n {_ր7E" .j*ƵXJ HcsTV o-901A՜n|>j.ÓRqx2ߟ% "_R, p޺:ی`>JxU]%[jvyLMnf,+.'xMtQ!SV09-wKM ŶE*l)nC+Ac״_5)nh(Fsu9~˩ƫ ~bK*1YC t&u|1c]aEIPmhD7,'|,QK sndWo`:cۥ/+2e5óL9q{mqĿ4i],OC.祀! MyhAݲ-mgf}P3kWvA~nxU-ma".pd| /L^pv47cL_Vi7.&l?ݼHOj=Soʷ8"|(`d1z]>Hhhq j<Ԓ~\ڋ>,BnC>Mw4?XFpg˕8P(1k#Ći7%e r4u>o4ͱBqdSUŪFȶj k3<5 ^Ks֤R*-[“- RNTbqw݊ w^JZx?ae6T 5roTM7%2gQ;a:=^{3Zy2yp2.ԮƼhW|o@O>W> w5g'IJdcH|1Ie#cB^c8fd DY}9l(;!)Wd0X(3mq=5Ţ, ->DW׆d(gL~|7J5/{zr4\ =In}}Bqů|m 4•J ҉J|xHEz.a.^E<#Q-g<8+oJIo˼j 3@ʽ=W]5i8͔&G p!K)҃Ƙy {b˵!el-Orʾa4HwF̡ذQ-pCf"ݰ2 bB{Ӌ*{r<ԘこB ,a(yD^>t>Z p9}LTo|OoT\~LjmP5eME=-La%) ,r#쟘3ZⴲZWds1YX(@2wnO5i,vP%)Rh@ޮ`;6=j! +H'} _{.bd48̳ &|>#\_)pJá─/rq?5v {ݰr6.pm!s5kƼ5|l/#EkgET(r2e*3 ־5+Lƻ7{ΰ@&W򻪢'yyK_hڋ$Ĝ! u OSA[[؄TE"rA3GĴ /!/kg 1OPePde6p^LZSnW-z(,nFZq mA㤜l_[z הu%lvSbH#2"tŨC>mI1W4DyiZH%U٪r;.6t>^LlTQXHR[uf5j  sָC d܍/yG6* ˵z0%;8Opv'JB_w]? Q`ё*h]hbif^W-1.C&?uXI uFy/dfLC=]h' ~~{WYOhWS0X?ۄ-t1>lG/Mۙs0R`CZQ!F:M'BDm K_|דK𳛕kKMAxZLZ(c`4NޜxW+5d~8/k]xyI֖}}V*rEep6sdbB ]>gDv2/?G'!VewC f#1{S؆Wh3D2P833$#u床ld%ㆥHZ_p+@F~(cަI=tOyuHyxSkuzPf ̂;ݱu[Jompx}Yv 0(Jq`)a-,.\q5^_ ]kTo%')Bw /.}v>{OFPB{ N֯ӂf75 E$1{K?G6c⡦( fsrG٬#NOXAs%v|\)#>{L(B{TG}MuF:pdĈX`FϿ>xf"b@TM5^}Q%J - Dr:A5;tc{+.#'AV+u IQSyw@Ù`uHnlx?vOlۛ=1Kq2ap|ygc'cT\n"Mݼ鈫 _QKJ߆\L l۲vվ؝XLwU"Id |n&o:WlqF;tGJzqi\!<6m I -c潁C;ꐾg}FUUTs0&ůL,疚Բ٪8%glÉ[rT FKH' GCRo_LH<yE&ߧo i)s{Tɻq}n⹉gR?$vZ>!ػL:MRia+-\%lU0]{cjZGr>%a;J!cHBAICը؈?) OM!pƿ ƴ+AOƒv^3em 6͟_y04I*Ԩ܃ Et &ZI(imK-F;"5Bl'cʧ%~яU>m?1գr2(&ΡT[I(P}\MgVoJ朞YşvOw$}&AU4lxPMuzNԛ$1YMh ctIc{Hr뜠 +JYuaFͺk]N9/jWE27KEYDOҩǃRPty:d` 3?S *0Id:{ED40l^F">F06I]!^&0rV^#G?yї& #n|jjEh^պp'XwS(Oמ/i8e=mhض5c_J!U#~0/slm 00RSJ-3d778;>M C;YͷkU+/l0Ûc}Cr^ۨiKj V!m3͎w|g:;%_7yH}6u{㘗4&[sErM#|w?Il0@ZȢ5\s':\(֮́$ -Iv55F=gBfmu $>lj= :nFRm`ok gBǙ[{RO'0kF 3߻ym̡~Mc0߮H}j~m \ `#p2Xt bQ!F%S: AAwZK] ~Ĭyd, ~v5:2.}YMY2WDFM\>c]n K]2,YZKjX6k;VsȄ" #ҽ,B>yX/cvΚBzDp2O(L}V /a~6af-CAxi[:O j44avG;er빬 8qM}ݷ4r%'yow3aJUyX֜S)&mi \P_RExV?;WYF>8|)GD@cZqc-Pc)vR@$S.rrVP~!Tȅw&(o@ VdJ WP[POh׫Ql)KrG1QPNѯA 6 olDw?*c5ǖBsGmVW| Y;@Z8Qqꖒi wn|k> y;[RNMƇ卆^dz&Y{ѹ~+ӏ3Re&_|SpxnSD9[o4r AG<͸h+?}  $hgϒ4wͳJ%q)f.{Gc @Nz݈o zXnq$BX>]7[M,( 93Z'"`^ 3XAtj+Kb;pX#߃S<2` Ah?q"Ž\~tru&4_`dZc'!Z~L}'PRSҒ-~9̛<^0ckg7ܖ- `&8}se6R2(䪻a M[QFiIG.!֛y EhH}HٌLL nF5D暐"=  a4l;eOt,o;(og|aȦ$mV6VyY[?|G ,J>TNFBm KN6~<}+$/6cTq\,h*_v.u7>JqmKon`4Տ6=vkHҕOQ BsRi[[H7kQۘ _O\CXbA @=wè>Ly堒Xrٍrgb_ǃA~YpvLbW }c:z`0>5A~πC6H&m2\]dD q H,;,&ۧAx뙨 #캼D:'8,r- rZ!^U}t$au!9>ы`0]jF>ݰ(?³/æ$#,\nt(T*A:>p H5u涿uB]PGYfJܪc¦fŜO(iEN] @OT jƾbvt{8)<f'lT7R{5qLƷ]\b,V'x_>e!SKt"N&]OО ,P} =Bo1tv`/={ZjW0j$)BQ9|rʐaTu|{;q* Vckb<7i;p(Tv|9^&#8jHNrx[Ü[Rū`%͍߰c(4`d#1 .wuO<Ņ^f(-ScC<*QtD\s ܺ,k\͵ AC*HPV36Rye냀*ukR[]2wLDfޡX/7pK<"tA'] Vn$(6g=P10?n*ghQ^$hpI`iud_zveH)&H;91MOVs *Ju-s#(e~T$wu@gC!M4OWVˏUw&|5¸DjOyef\XCԇY!}g識+23O)}[ d.VFb0y y?>\_?Q[&^cBSwK ;P Ón(G?lo4g*L1V!SP9#}ꄰc4`{"2H9%)$ş0k$2RPNЮ c=1)"kCs5W&-{I*ܪGU YSU(B%1Kf:ץHڕtI:;;56=Cw̏sw\rPNs; ~J-B1JU6DOt<|O[?g G$rP43ڙG\C˧ս KHcR2XO}Fm`F,m@l*HQů-6# ۼbX {})tW2(*rfϏ#}}J/bo\OV{ ;UA"c\V;A$Hx/A]7YV 3:Ʀ}QçyVq'Qz{,rH:)ϵ.+rcۯr  z>b3>F#3m'܊x(xhNc%6}H4'+d{bxHCAqNgH5#.:O&ZGBDF AH`-d?@! ҪnT1]v!=#56@}'tҊ2ILK{c-Vr`.V {,Fnwj`:X21Rk#RlU[l`Rud7W|M%H*']_?3rbb'~#I]x/|p;︲VeýCt=b3T _ҎFH ٟFyw( MБ_bхQ^7{q+А._nK:ylePz `pVRd>LZ]yI;H\{Bu϶+hny~v$?eBԞ@eaYד uM$(zT?ȟO$3 '`J\-TE|gMҩHI{ۣ;qO]Ta2BR8 pqpf to1m!@9f/~SlOuO[ |ʘ+!7Cܺ,##FiԾ` q:S?{c+dٙj]Eoo!(ܧ}.Z6a!=񽧲mV¹ c >n1"1"yȀ_gm_XL|3.v@%aY xKѡZr5լ1Ce0?Xan( #(.cEsajv MZ}XiTpN oeOL fbֲ~T mB$r*.ApG'/(ء:ؤ{p^29,81-&1f%8%z~2hPbIfX*R|гT.?)Se3,q259/31n*f@d|ݡIwKW=U9Tz=L^v2~gIts ;Pw@ORAEeMzlb͝\Emq6F݂0"ݐY }axۯfR%yP~aKbuMb:SSgv*K24i2OO۶iwSI^FSJF'Ti\7͢] h:Nh^;H.qBl (4yh 1u)ce7Mg rڐ?ZKI_HpSI4C v'@DcDZݔHѷO\#~p"E:R2TP M}Nt|&Mrr Z38F8wAI 1`"k;<^S>)E:02cۏ8.6`GueN}T p"F?c QI*wXPB`pq?Qs. xtKmWJ;aiwdg,5Ǜ7YSAh׊MZ)JCxiMvBku7>}3/{) ЈVu{U+yU Nxp7x+tI|gp 1ս֫GME<֧qGvr뛘aTgss5i%3[SW+;s05mڄejZ]y0 ra?z/|IrXz 46[wo/N|N h$aC;B*YCs܍Yϧ^d5,QyzάV YѨ!n7q0 IN"=ջz^tgqF%f kSD}qKqC/FfKuS!#4I-~gfi SL"*7or-/V_B9rMygxc0[<% Գ[wdXi&m?X"hwNU(L|@Θ*Ui;~p r;{w(k!Wնum*A Gzbld:3ܥ?[Q^Ffa{tN0 im3L攫HZ^l ~xA1JzjFb]5a8}$]~=R;5sV^p)hV 7Q. yG9dB[9ʢqjrx:̄Ğ..QzvT>'<5{{!p<"x=-L!+|T9%n)ĺ2GUFFn+%}Ű ;hl+v0k&Mu&J떊}`y:,xfo#W`Q(Ix?GHe󐀔4s-Z0=c%EN_iV~9\;I ӅjnhbD@ђŖ&H$8_ַw fg[m|$'wta,ɉgQ]y"qfy^IΆMfLcpYC7wpAf'J@uh6T*ifaNH'P!sni4v%Fb Kgg1]wM8j: r dXs&t{?|§vD$ox{ rzhgh.jsn: [g@ϕp^`l.nPU"3EWcK6Zz4oqdwgbZ9TF- 6)тr<ɭ3pOYUh%i_ o[Osߺ|Q>L8uVZRkפ. ptPlCQDyNQlѡwb`*,СοS݀O1Atty8dT ] UQeq6].;n-ǵMJu)oŽ-^D}m /xͣD'^,9d]CY#_]쟻0u0|EWxE)HMR?:@ߔ<`D7JPA+w,O+|]6 H&Ӕ*lDZ{;ƻTUP~[qZPhW@ HAVDSy,S\D{ { C'`YO̚6OIq;hkP;גNK"̶ ipl7Ճ-4& #yJX>bo%5K.Mխ p&0MօwwW 1ݴ=KuX*"F[Εlѽu# "%T&+H38_#y#D\Y`U/Ǎl K=8^g4Ij-(2PY Ia痥;Q~kʃM#Ht׌Tl$-./QLdUD0_qm〮qVftuSo\ϓf47sJ1s&]bgvڽxޣ/=l2Z#Ջ)skjk4q$ Y5MKCHv.ba+F0#_e?j/Ϲ;]]}%t@ٚh>2܍BʻQ;2ƝAwVawQY tt?%3ά@V9҃s܆ mX#>tW/p̋Ӝ/)v oHx_bdxϊrCUX!CN%ȀdZt2TmeP^8c Rހ _.RD!Q ۉ.F1"eShL= m/:;$o\d3e:W1SQ;1ВtG%?ND:^x57ҵ|=n'~"DS"}ZI?#$=/1ԘƖp:N5XO4yr?& e}7Y!3 f7-aܑ9}=s<θXp`Gw;+tyjZ+)4 fT@`z[4dX[t݁^4h֪TnVٺ|:b ON_--7Rar~9j$jii&>\sìQY%, r㯚q`o*0Ϙ=y[$࿡H/0<I|6!{ƲƂK|ٓ4bԿKh4 L\Fb-y7!ŽKXT}yؐmDY>c7oL*w&Ȑ!s(!چdshn П'Pqu=cI `侸Y99_kFPEm9yi!0m+')yvG俿Edet<`,n,V?%lɒX`Ҙgxf5 AHM| =8Ȇm'9\u|84%I+tMU_pmm,vkzkQH66]\:m w8/cd~IrDw/מE@Xݛ&Ng63rCiODq2ZdjNwj"L bVBu!$LNFNehS ҶT-zzU#~q8s)P荂%7Sy8 .Al!`b!S K-t2lҧ $-gQI=N '`݄a`o!|9lK-Ҳd)ŧ ~췪^r,CwA#C>DR\rm™,gu(cy-F"aPIAMM#rm]=MC565@WY\6{4u}n0!*S ,pӬ9j~!ʿxPyѵvnn~td6õH`$:%T 5uI8r7c"lS}`zš jyD5sP(C;1N,Cvy`LȨ sW'*dYDDKcM%;c֙SGrc6/F5'Bn6`s=n~%R[/ngaA5s|lc&KL$OecM 3rVzX5ehnb;Oæ%+^<[mVtKPVxgD;)mIQ9/f5#Nnl1NW4)_lu;"SKեK5 ~ZDcᶧT XZLE̮='Fv[_(['$C/2xKF͎ȐwH"CRRO=CX|78.s,G=u/A4Muf)YkJ5w*E kJ3s L% [8p|*?e=YZ)6M QbZEA P4 1RVeƼA#?!ɯZr,~4'e;,5pQ> stream xڵUT\۶ ݝ)5[pwww$޳~jU9Q(ILlb 'Ff-ȖAOI)4t}1t8NVffnxJ8txw@'Cw; /``d,@@[;w 3s?k|b`ҟlaFdbeٺ-4 `k PjTEJ ʴ +;:eU/Br*GʟO 蝿GʻO?鲢*B* ,Lp:8Z)/nTj`kW+_T-VWcA&t2=XA?Ib;m[nw?bpG ʘ:+ 19A @'C'gG_7Єo@ßr2K]t= ]c gGoh@5{?{f&+$')& .<{w@NnNEYO̻9wLDlmlY;i>9:3[V [Wlj21wg;&U3Pc3:@{؜OoO;[;#~t4tޞt7gX;$G4S3jb vMl@)W-1gkk9C Ϳ:0C k W:U9[C,,܀& N5oߕ@f@ #'ֿ=NtǏş]V #/H$dTDAƶ& 3+;] OwUR dsv:QnN߈ d `2? `2d0YLLfl&@v?{Y6,uA?mH w:t8LζN5w^a7 {EŸ׹dFL +;9Z-L"k`~X_(3-,l`~\l=]:_g@71꒭ Ԧ2тr(Jn l~ x/d@B B[ ]dPeVkRxj@_yTNf \F[|1@uT!u g NyFkK35 *~'L'fla*ݼA~]o7}jƹn?&#FhMQ$,*k%'ʺӅ#g4K&MvbbxޣTK|CVWr Q}EH敇I1UKy֑[Fy_t"=1RC<K&c?mL+umҀFifE&*ex*Az:rtbX~~rps\DsxҝړeiemK-tFgMI#x>h~W6˭*At!-XϻX۹ExI+֌z|c BFJ1{E)$2mѻx\:JZvii9xZrm.A@wCOlҳINUx4gE̕w3R4ySf|y"76֊'ok|ap֍BG! aWYL/q_^֯) C d [=ҪaPŞ?+ Kf4>[QǍcc3Ih`$cu[ή\X?ϡکx*L%[Zh퍍wi$ơ.vѾo1A eYTwE.,GlirvVPj@=Qd;jK|2]:6j$ɣaH䙸ɷ0P}Y5ܽ>T/I,9ٚlEzfTB0[* 4%K GGAkg*`=yzͶ5XU9=> *hp`jSů?͝Ȉ&VYlxȞٔ0'$j{"<5Nixf"SyHRmqk+* *|>>p]rXǚU{z.fPA9SXVߛ8 Dki !jo,d,B5$SJ|}AHz2E_HoU?s:(tU,h[u>+2>ߩ~1-i|U#0;,CQA"g'7_SrDr9?iM[EDv.? YT񆘟FfF1#¶^Ws?gP7ڑFRX%;oGoQuWqxcP{Z͜q3V!YFޖZ"Pϙ\O0jM6̃zR{V]VŠqZCҏH7z<!2p@7 JijA,۔7;S1d5ӞG?IVg_ U\ _ bsd] \eŠPHx1\$k ^_Z.h56ЪU?%XRHk1rY@ B@ר&~jP_Y T>rKiG{X#|oƄ*b t׶Z Lv} o=.ҿءU; " &,"-?G,qXK<亹9Gf7A`{S@ѭbuޯz7UΊyzSit{c2~Ag\_yx7ddnޗSX-𞮍1 @j$ ,(L<-}+>) vAk v~;M/S>(OȷkyA82 c= @q.oy2 %hYxk }j,b֚# 𳿉εQݪf[Qzu}LՐT{<}а}w]uؽd$: ,|n=~\bfr4"<-$CMha=+|ai.g?nՅ~~[W?[@9-zlyɍ 9i%r"qG5D]N FJ /_bzۋn5LA`ǗOQfp5zb;Xo8AKjٗ6f9y)#¤RJ#9"6a!rgёep~SQ'KB48Dxz*B87fDB7WIiEٴ\g:}a2:;tH–;` }UJZ~y]9yMf,# ur|aOh|R$Q*LZcEḱ{eMV̤H"2[UQ/6b&p=<[)Pjҽ|RlEO;^X|srK9+4. fYU&TK~"fD+E| s0]b)RVɸNI%$΁뚦kWyw8KMC . *y &6r5'sYͽ^rM_F lg8ƛwZ=B~bn% G4Tn` 9iaJH-vpTw[_70ގE*\?3= EOzGnb$XL57R'\ťJ;:ow~`Yfea )xjx#|lMzc8%1/Țꡕ6{%.sac|[0.',cӶ>2ЋLN]3-T9TJ>Z'i.e^b>ieȽus5X3^zZB[qS[[F12CwY*iY.b{>Yh Lh4ܲ5 xi1f y-|LYqv`*yfF"v½5 %T h9 1lhsNYWV=n- jJʺ#ܾ7kOUCx}P,3Ъ޶7[̣]^F: s:0Bv"o2L= Ӣ~[J葮e!Pt oB6.aO3VG/GFKZ{(L,c0OϜTfqWJSIvBk6ूL~QMwPԹJ}θ+p (a&% }SAKɟu"m'َ%àver"\]Q2 sC?8N37R Oa"5qjmU ԬV\_ CD$a:gCq,(l8kw&{-y;CluRׂKot΂uD]*zP R_Z\ Ule+NrY;O;E`7fn$)=d>оYϪܴXB :xܒj:`f-DT9t-:>LxNǁc}ckk R `$M@2𕨭R^DbNb򕗉-!A7nJǘE#{nIꢤfRE)᪨ uр!`w-b~&9U8*oKc+ˁXJ#q-nѥx¦\ vMGc܅:gw^u&MRε`4[ j`\[JKߟ?z)*u&D2h2>Dȭ4Ÿ&u}-`?)?E-A|%5&{e&*3ІdYE@gUҰݨlbp/L府@ P1L)F,sKnȆzZGs"/.nroV,h nW|8'Qp`cVqQQ6w[wsDoѴ T`7F8N>T5E^ǶZh ׉_](>'z?1gAR/e|iLR`KZQu4S쬀ٝނ4nX ~!){Gm[`8uE^~ 6B2'%QLZ;8qdh*Ek>Zyt^d[!jg>`%:ڨ7wmIR)mp.lAXC^*8BcR̳I% SUJ|jp=gu毊\)=PUɦ]t:=TrJH~m1lx^)R{6#<` (ě-˓r.f=!r`4\h”]~W#\<ي bWיfUn6*pt)j%?W]OwB}T؏Dp,iD h 䖨D4jPS÷[ȫ3m0-ԝg(Bw1yY+/F6ADyO8$$R%Jkw?d}V$wmob{YmDχ{Y5vjDcJG[Nse9ڻGoT}N3`s>Y/r~x:fA`Y/Vd0`\sx?=q' ]~htWM>I;Q1mHpۻ`&_ U?#ώyJ&KS'-$M͢1myVBouZp BMKOվT7zZ%|{)j[LaݎF]~'.U|jQҹ]t5V\U>VDS?r!Wm3xߩaCA*N @/Z^DT`ez:F(iفÙDAj+1Corj*h94yȫ],0eC6١e&#f!0h}d{(Љ -<ϭYͷj{sVXD!+I1mIS-KzP&6q(a$$$,Tݑ[U'$M*IMlr޳׈qTT߲ޏs3& ȇ483P "-茶 # ;YՋ*˅\] 8Rllc+8-r9I?Qna#A"m/x_~dV^ilAqunnn<Ӡ]ӢZanl+o*âBhۯ]Ғy[ox%kX(SNdƝ> 7tmWGpʉg< /Ua 컷WSZRվws jz/xm mDPjaHprtF8*6Ќ scZQp haV/5 z6Pn.'vxCZgݠZH\li~y@]3&C(,vAS4]KD¯:G=!V*%.6ιFͬB|af '%P1jX mxONir#٠<سu)ЪN,8=gM.fBgI#CRl%Qg) D;z`Qa J57Vf63OarO]iv(Z# X?O1T~^d|]n_@&?ǒHF]Wͣ$[!'|[tδ|UB^!sRw*q 3wYC}y)j҄=|>2}G.90GGGhVfͦ덊:|":OZXI|ˠͶ@.ׅOmD煡 $_njm5U;m[?{ 3-|Y G[ZbYͱQ[/z7dS͇58s䮧fw66bR|LV= eo8 )4o}En[E յ#ɋ/Qw]t)I!v&L%<ˀsJ䑒:Fzdp )!dymt*uL3ƄVdJ3xчnW'H.D[ >Z!Dꁘ+EfTegl堏t eh*Y0nSM\mw<-Н,Lz]sZ9yu&爆(7Lě崏 Xh+IYØ&n蹸˥eI Z{&K} iBk grk!{@0Y҃!!"%-ST)}4+lPhԶF%2WQbP3I\HϨ)bc47G1޵Y ߛp"ZC.j.]ۜ,u )aSEtVIϜa4|I5|*rm-HV4 ~Dz|U _Dom .AY MS>AZ`Lh#H9̅ݏ>& S&-%3^jCG>3[JlOAs !C$B Z}XzKh-aCS,-A ]9 70)ˆ%j5pgƱ'#Y3I~az@1ÿpi}O.H޳<>SO;t`"l#~sV 7"tӜUwѮfI?(Z=:zܤ}@1ľe < ૴4G2*BPUA5\O8Ǜ_*uQjkjíe/lGXTj$?hzjG(kf㦍=5Vi(&k|3;Di:PǦR4o6HqG$Q@44mG1}{fHDlukF˞l9#&G i;Urd9s'$&ŽBա^({|.}ʕE>vO6*0x]. 5h\ nȤU"&BW f$_=ůC96YFҾQB$ؕ&:!_7{ePYlMHXd,lNhq[1(}G˄֒l6`b#V΅dtOdMBa$V媋@)!LhiUPnD3(sgx(GTPkȋ΀:R`HR?DLg4ơb|kHC 3ذūp'._IUK#W1ը*r,}vܓetpDOaBkRNF"UAz^ ܀]% [ 9n8W>*}] HOXKoA RuԣÿoFJHܱV\R E>[e燮C_S2|eߖ$.xC= K aJ?yK?F9I8[~M<hԃqf7@mZ7}tv]u~ggW'o(awƹ}6+*x̋BzI憔CDLk 4dބۏV{bu G_Q|[#Q7DV ىdA]"yToRs.F $I#yn7,Q(ߐXd{'Er%*$WmD L!(d)rK|9E${tv% ػ ](gˡt羈RwxXa'e$ɉ__& ׆tj S^e|:RS^ i&7^ "MasGT'?3?[؝(}n]Lơ=HU+8;c=9#M\ڂS/ ,12Ce'[ˆ_\ֲ+<9+fw{a:oA\x'.$Ȫv"0bt柮:!KBHBJZRч6bɝ5sEK!V7;sz:/N\U/'[` endstream endobj 74 0 obj << /Length1 1608 /Length2 9144 /Length3 0 /Length 9967 /Filter /FlateDecode >> stream xڭwePіmp$K!84nݝڍ;k x ̝o~]m9k>)U@F`q[3# onmbh# lk:ّ()Es[QC ,,fnnn$J@?)#t47||p[Ym *`0b[" Rj y5`hPt227Țm4[? OkXBCl'D;X;:~6@l6VN?^& 9ؾfX^m!vkUEQBv4 lM^3ANZ{yB m+O-#0dhgeZ/ 'Gs28M @V`GWW?gֽӶ9leˆZZϢH٘3 v; ?;CJdkcMm!%;}"$o&j.>+0Y756r53 ')lL_24w7w!fCـV6W-/1U3scK?Cۀ<y3I*|oU7Wbч-迌?¶fNV+Yl^C@ !צ[?-1 u'l v#-~HHNjw3Ufgڶ$s<0V<7ޖoDZj$D_IǤ7i5X-ư^lOwc1A)ӕvȥddﰈLζ.TҨ&v]CFr~px Ƀ(;ρW.Da8J)!NqM!ѻ5ԒKnQ|^~XoDiilZM/~[G2sr{X|b0 ;Sj ^p_ ۡb.@ԍP!#CFw>$` |KC]E\dL]?` %~Z wVju/GcͶ_? !I1?yO}{At7#pBg|.vF2t@/=l.4?k֡?f<^靴3&yKx8]eP*6.z%[g!vaJ)ԯwV.+=·T1aqLq>cipA0DA/3.>ӳ sE)ˀC~2 .v?nnI.YTYR{4;}S3q+$[]lq:ty.} #xҐv\m3^4<KI0+RLu)&-Q5LbȨdȧEϜ+_ c㥫i9HIdr^F#WRI{W5ftKG-12O&ѱY'ϯ\t S iW2'B3{{ WEkw)+!w-|:b>B6&0zlcO6ˤxxsZfjq̵&({+ޛtKL1:ܡmLÇx={y.kb ?%S { ΗUVu1.UetJE~c+?Jϒ˞~aɷkIIRܨA 'tԾ!N@lD-/W$ T)EҜɄe2KD} FfƺVFb=|a%xVܔgLnQ5c $ ?iit u7hvLe?(nwVN@:|Gs/X8RG!@1>a[{nԦnKxh!X-pBmUރX\F*  !sTvXՃ]b`IO*H4SNg3:@cJ>Uu578PFy'#cՖ ohI(6 1,&}[úGX+O|)5&GF΃NUݍ^FM*,s%*x:u# Gr'NvY*]2kh`6]np~Pëܽ_n0:ءS H-h `͂ާzjRl^{c4pW=+t]8ĊW҆ EC/-ԶES,[ϠS1iꢊwOR [J!ԶB&Gu/lzcsA[ uQUӰ^7mg({zyRgtjODn;,qX,k & 8$`qDt}0`6v. {o!glSQk $ٝ&O~_i vыX(8"#Lѭa{XmCMKߑA׏[[0F+nv>:zae5Dx1,#0Tg{0F/b6O{ t]kbߌ/44ԚbDC.#0ށ D*xia{x*I!;F?Ĉuf!.u;| 3~%kH~Ò$^GPҹxNSl '.ͫN(5:' u<pBQ/y fnN,B#zL\&* @XN?~|qJlj edy6Bt.e-ZɘblhvB:Q \~rM\EUx L]A3p3T\>ȿߖ"j`OsEYV_?=ܧGИ8Შ _'۰g$@N` qqJI O\nKy!^d(*>I9I ϼ3B@Fmv'k¸ܟ=>#y:FZb5i`G6>'Eqtۗ#FrV9ڞuͤh?A}nJTg(i1qKi>6|o!qY p%V1S 6b{P|9Aq$˅ɲ0PqePYmg6[Iq#/c&vѯi3JdB”L#5x9iKٮkwY3ERw&TLMh<Ø>4Y}](3X谱MѽyzrHEbKgxχ\{a'<8e #^98UD#U#ݧwS^gkhL|Ȼ@28r!HO 3͓ {vf£04ίR1vH\U硎\J"R\ث#s듟`oZ~ɘUebrv$npj~t0ܖ}\a, M!d;67zqaVN%n'(;=`ÀRiđV2]p?ZL::^?%=ܱ߰jMw"BdbxMp{bo'i ^ /J)A!Xgce sb @#[8EUX5QgsxrŽzgJ ug)y#5; /aB&TMGz\Obد!:3{cƱvfMYX!Tt ux<̲FR\}"ǾH5َvљ'Xɛ/']뽕W Mt 9: ";?2Q-3Q6~`46փQqKٵҴVzSD+_I`荺gndg'A:Ё`#Y,cnqHk>&ag6gxNB{>5fgj8Y* T2! 6b%ހ~LKuש<^enWTsZ[>ak9/ iB[q\CYbvEF EsbI=<v nm铕窓إx+G;@_ۘ)8s[2SN䳌 7@~{᫉x#h[T&y䷩9;Myj+M{_Gcop6"4>9˷ 9J.$|Kʂ1qf6%-)j78:_y,h2kB!\3܎K? yN)&z)\7U=f'}%6--а.;Oނx\c[_NedC㡌<֖!^DXKT՘6g(}^aOC0UG3ޤ\xx"5S- ?XV6I]a)[լ d0Xq],]jԈWkb00tuv+YHo4$4_sR&9~9oL?"ZٴH6}Ivv}jDj%lo"'}BmZfHٷޝBo-Ukz곇B̗)sً":F7F)u\F0a_a6+8 ؅LvVZ"h@8u_.6_$¨Նwx t6qx,%\~4/Ϳ?6Uͦ:jUKM g4V:%X|?{(ڢvŠ%vẏy`eJԂ׫~ۍE;Z ȉ!#0NE2RqlǸ@s">V(L_ϫkMdĒx#fz ZjK2|g@4\!MɫVKsRk=oyv%Cӝ#'}.h< /a"@ITX?Էv8-z_Vgf[V2T,[I[7+ rd-WˡvJ>z)Q4<^Q>o>;Ps![3F :VC)?CS2$.>R\<F ZI\q[9t(#ZmOg/ L>#jģ. n,*׆g7e)- Gęi&`~1fD>8ZA_#f2ONr g@Ų\&Ly =ug_ytD@JvJ[tv zZK%VZ* Ɨ^̓5.a)x;S{r& yuӊ/Ҟ/,GUӲ0uz, T`"NK*P@paRMN񆻂T?س[Qo4g$]Ld۸΀)#SiN=Z-X)Kqa*%ڶWoI-=ѿD|I =/PQ޻G_!藌]Fp׊OOY7:}g26D$ޞHc׃qn~x+ BܴyYs*]ڏdira7qkD\%I~rA9KZߖve绛5|w5֣!H w W~afLM ޙv3q3=.ѻS&v/!b-%uXh06GfǪ[TsY a#3O{ 9 ʧ -&z3ɯuKlU)Z05o|X:= Fyz$!^VFƖ"=FUfL7* 4nIC BKh~|ܴuӣ~'O_`GM2#AsC;"yso*Xf3W,ۍ_i{M'_7/dA8yô$ϑު(wΗӳMGr@/HfƝOW& CBTտ6.]vJYU |ߦd {b ]\0hsYtqOEb^c!UȨUlTQ7ȗ-Eדx)?̂U> W}>+B=Qd.dOjĉ4(w҃"QKE1U%m~0аk7 %hUꗚ0D #xU B?ț@L=,{>O\Rڣ]SI쫘i>'nu4Ǔ9XI7K]kvJS ~/G[E./?sD!-GPp33_ :/`H>pY?Q&㯏lpr$q'^ηR#CGYhJ^_k<^x ,Cazluש҃f ^MLd3G1-Y͑5X8BZP{4i$o1ϳ\8Tlcݧ%ݤnxYW*i@ݗ%+n{ˀ-V֛aLwBwiG+Sk;Y2y_iu=EpInm9#bˬC3$B ~~wnI xHɉ<.>n|+\1;:iietJ>kP+8^֫ >g9&˶c^$[58=}!ۈc.?m %o9x8si`wWBX Q`"q S)/dC)ѺhVB@#,`;a3H%9 Ma+ YMg9:DJlڶ CEgOIGm8K""S̏+PFS'Zq&285Tk%~Բr׌OI-HQ?36 ޽ WQRA_fGXG-l0ա6l-ga״oGse8L҄>@q;hNeU6x)&~¸uؐ3rɟ깔*˝\-.c°YSrP9ltt>1uIiAxٙmhqs .杸4ptvSyHhK[ Bc"חj/pGCW)FN.Wƪq6 6Z<4.ڄxo}݋ * LaBiB䠖ʧ~ŝh??d{#͆@1H=rc̜["'{yJ6$VzW|oʋM(xAEmUh\wj骹:xC=\ 11"{Z3/_@azJ3|7a\~ɍWI  ;2M%̉·FB]y1DҍO{?W7ENЇ%VxɺɄ3L8]hi{1y?{K^E+"u-|6ء wMcU-QJj09=|:PsiO ܣ!R>*0&.HUMb4c qk;4rٕgA:е;˙ğľK3'Ս#q{yr%A~kpdX1~Bm%fqrDsuإ7!IEXsqƱN^i o(TWy8;+ed_}/Gʱclr]Hdü>~bCYD$Nv9aj){Z0Q4:GJeԽ1N#eeM|:NL@AHWnsƋMZ="[ E Ƙ!dQDwۇrbsF= 5^嗐N="xbP1+Z6߰@;WPRx_ % AbqNysa]uAq+ɂfI?rRv5N#aW2  ߌ^VqQ> stream xuxeT\˺-@pmܡqw n @;HpN KpAwH=g}c9f֢f;[B䝝ٹ856I] bx@:Pwτ+uv?:U+ @: 4\ξ ;L:[y8Bܵ=`0(qsp 3g+7%$$Am O3H. NjXP?0ٺÄ99a 3fqd~NT ,7?z& uX=Ͼ;9{9l uYƩu񀼖_gor meGHO9 7H<`p:P+{'۳ NsrCl A[y>z59Abl%jW~W+Ež;ǯ{Aŋ~Wؾ7Z09[VcVQ>=;/{!TWaxQG jXghLS>ĩ2>72xAwF{.(dU BoO5Q;evo#R10n_UuY/K Wp?$3,~PfǸw9{ce 861d0ȒY|A40Wv)'5^4e9y* [+wcܣ_/mLcCۛ3fLG{v*onՙPi9$sn:mSίk'$U$z4}vaޤم2FM"*~!gu'EE5O*Шniv*J˱=A^ cr:RcrQ{P0+8:S;0L 'ÁQq%OQ`~+gzdcN M^l$"V\QM"1j ~ $~̐7db,Q1Cuמx<JWibjcjzu :=n#`lkXN%,67h= 7*pfP&S?YÎ^;,eM]^ԧҩGZ,b=)(=q)niCaiWl4?.>6Kb%xq Z}|?y $i:|ۋȉhL Zت2 U.Mt^0? .}3zj:yIyMd}a܊{|)(] fiپE2^wzHsBh^bJ?R  ޥ(h7}ߚ Sε*ZEi^u08Xz?3uVRKOT1Vu\wgb jш؉류Ir3 l2O?m ъ9̹ưW8lz'xwM"[uuX y_M<iKWHsf.1*cBnQb6_R[>i6{=zUyf%\JM .A`lkt?bdNnkB%^j1 /|r 6cnіk !FVBJ4=W ~t|n.搚:7Z1)ĔəankAfEp) \B0oI32=X"]>̴Ijp ͅ!f@H6+m6AVIfTCGͫ可A0uW.M:a鈟vM-NG40&9T: /%zQ~:VTFs;-mIxܢReouE7 ķ[T9pʩksw0eҧ,5|Kr't"1LDhXPS} JQ2o47\O |U/SQ_/ZK`L@,}ԝ_&cKOl厸BX9@O]=e:$o仂!74=rzEOrt6/Tĉ>u- :mQ~hNp2MՈ5~kOxOc0#q"Ii}\^J)xrX? axhjIuᗜ8LV _wվJ9̿?-=j#d?|tJxKL̪9wMVJC ;ڗe>{yDp)6q =DWY84{jѴ|)?qfNQO @Q\5Q%ު#wF~vWdE*{+F/Yn.K% 5V*VGmֹb'?uAàY₂&B%N^y=,[\ų7qřwԻaqX Ze7~$\kr 4=A[',WXˑbadDyv+~q-wAV<1KD.Հz[Ks7S#L/ۯr|ڐԴ?x] 7FTXctyGe`@Igq; SsªE;iFe%af\ACAC25ŋ ᒏXdeJ47 a4 #ajW/]Uv߉vuT h RDz*Vcr\ka$s|޸[7^ª].3ӼVЫrzT ,t>Z|Iqӥ"<2jg[W}%9$Wܥ̻&~33y1lSg#l;\B\ohUr׺fbQ )@{(s'))j=G|/ ~t"-&u[{ Ner;&ݔJAy&DL4X瘍`i[ lɌ a QCBrU#K qmKo*O]T[ly^J֛߻S0ڢћА^Gnw)l2wDNҮ6VuMLd)8V*_2֟e1|X?v/IbH:'>#uX*C7#}?&'p#4s2+#>'SW%-բesl1|}of4H3CFI3E(vBw-Yt#v7"e]37 Q<10aEgdPC.)ϤTѺJiRbjuKhlUm0ZTjzbV;(N xgDyIQq0P/c}Dc_l#|45́D|Ƶr 6[|ar{AZ"_ǘ68Kt#]&jC><]r7@"!Zps;dk>-/inSdUAc}ɓ^ 0Ml0 3gƲIď7UuKoMSo^VK#C*C"a( Y'"ۉO1cc_&>5q̛`l& wNJt)ݳI.d 6}WP:9hp @-X߶NzR2貤,hJtpqu^JA_ w }g`᥊|ː TRO$pf%]a, 4HO*1q:wtT^Ÿ~@9JaY0N)D6OHw',fכ°CZW㉡v|$g”{y+o7; 1$l;S"kȥanSq$ &v2] 9HQŅ~*jڊb"$$Ck*NGꯦPSIq| 0-95sOZ\^A'>(27U~x~:鉍|˪M$l`Z+tgD \ڙNGfJ"-?6H`N'0`ӝ6>kJE}("M>"`LgbB|z!X=oɧ:T48Q7)F^i̹~6f'곡RxX|X=oWvSAf|즘^FL*g$}2b Tq ƯnM0b`~-D6x,Z%'ɜ,u& @ϜM+$6pF9ukId #1 Lu: bF&FX8327b3r^d3^}\+kj¼BRFXí~-h}?[QfZ{Ƭ~/#&MxXX7P Sy&ͰyA[Yp7ΟYU49&7uX5HƧ%,:M{YnȌB~EhúYPl0uZw TlBٟ/OF$^ӭVuIJaVylô8 oN3/kFjt>Tƌ/3lcg%Cth&Ԧ 5o~3^ϐLȺ7cP>Lz؏G#5lG6װl)\[A 7(iװY@;!X]e?2=Fr5֒bCx~<:imۿ0w_'@1 YsNiԋmJNK ė |C2Ɏwd/lE ߎc#i"paD4(tWCzН^:q#Mٰ l#㻷W&嬸d;:Qv\vݹdq0V9txvʼn"b4<1~xڛa>"rj ﴊ5Č њD֩+Q8T=h 򢒂H&t$?.|#¸KK[ǚ~Ooi.3&}w4+V$#nC,ҾW0-u݌gt8&YRڙ.YnkRt78Üui&n66Vccb0̠[DZOY;ɰOOjF@SGM1FjB=$Y{|}]W?+xzDx{)I",I r8;; _~~^A+ ,~9bm%#HBn+k\I46NsoR53i_ #Ԛ5rSȍV bM;r*ՙDVVdksہ^0xHIҘKh:1k &ob-$W}8" q)eq5zL)ID+HD endstream endobj 82 0 obj << /Author()/Title()/Subject()/Creator(LaTeX with hyperref package)/Producer(pdfTeX-1.40.17)/Keywords() /CreationDate (D:20171003062250-05'00') /ModDate (D:20171003062250-05'00') /Trapped /False /PTEX.Fullbanner (This is pdfTeX, Version 3.14159265-2.6-1.40.17 (TeX Live 2016/Debian) kpathsea version 6.2.2) >> endobj 5 0 obj << /Type /ObjStm /N 71 /First 541 /Length 3055 /Filter /FlateDecode >> stream xZr8}W1)Vv|$s`cԐT& HQdkl4Nn4,fg Ÿ )2R3@),j&H&CzY1㦙ƒ a*4B&SF'>~<%0~{ ԟ@D>Gw([8>$Tc`C@N4!V,|h *hiFDDLILK<CP;Jb4% D2p 2Q+U!tT 5#ǠW,'"LIH\T2TK"5Eq4D9b0Z’*|^AApO' (22r_b㧌g{^1:Ӳ~~yt:6+`W<ˉIGT2Y۾սwKֆlj*?ک)t0rjcE.<-afHHBUYL{eRdt? Gn쩩/Jòg'g}bϾ 1€ym䠆~bb^MEQ957t\ DOrXl; 9OCbۛjnasnn] YAS#S1 (q/ftL34 "X'^ 5/kY~÷_mk7~?캮g|7rnLa1}hOC'&Z/ўOW1r O- Ъ1^QJƁg#n I8J F櫙3SV޸(C62 _4!HMJg҂;!/-d}:R70/(:CbP>L[@, =A X [萇 haz}xE+#2hqT!|^|>\lj*lҖߔ!rND:DYo4ֳF#ZĿk/)bK|L OhOV`rcH93~fm]\լ_NgfCsrc Z-\|{$8# l$6XCm[(/&nmK5Ue=wԆNV.%rm&cHMs_MadϹv0J2@eJQ-m?׮ V6շ ()zM=]0P;<{O퇼v}Doȷ&&8)D(nU2( ҆=[OoѳwoyENM^?ml,\AuWun8wrf(wbiŋ'2 IHkS쒳DKa% `/gdZ~50o&3nx(G sOm>HpՑȦThuמ&$mή+4HbbaHSSޮT1oDʈ!6Z8$(7ӻזO:paã4SLFuR7z^R8.)EN)AJ -Rak?C>_5/i_Q:mINNz*vŽB?J7i;S Wc>>zAR >lAR(#A]g~=( w OGEʎě.:/mB{k:mW{}j)lO`*qLXVnZ\Ļ5Ӌ&v (tSW?gOl%}@6jf{^>,Z7PXw+UXRmX˰VX7G+-X,%#ނ,ڢUTQm9uk"=P\p'piӱJ߅ ̂+TNÉxfz%ʍ͜x!G}W=͹}4_飴>gTwt~5bd'Fl#uhگb;1bdO,Fub;}11lBm!q+c~K=h_5$t](0fJ۶k SNn{nXXw޼i~#?Vff&o>fOTP endstream endobj 83 0 obj << /Type /XRef /Index [0 84] /Size 84 /W [1 3 1] /Root 81 0 R /Info 82 0 R /ID [ ] /Length 203 /Filter /FlateDecode >> stream xUaFᙏHP` JRZuЊP ; ;*p<=gDD~H.D]}/T`> S@^b xH) 8,Tij9ha=@0'( - TU]*[՝j`PlսPD< endstream endobj startxref 144700 %%EOF RProtoBuf/inst/doc/RProtoBuf-intro.R0000644000176200001440000005317413164671344017037 0ustar liggesusers## ----init, echo=FALSE------------------------------------------------------------------- library("RProtoBuf") options("width"=90) ## ----readproto-------------------------------------------------------------------------- args(readProtoFiles) ## ----loadprotos, eval=FALSE------------------------------------------------------------- # pdir <- system.file("proto", package = "RProtoBuf") # pfile <- file.path(pdir, "addressbook.proto") # readProtoFiles(pfile) ## ----readir, eval=FALSE----------------------------------------------------------------- # dir(pdir, pattern = "\\.proto$", full.names = TRUE) # readProtoFiles(dir = pdir) ## ----protofrompackage, eval=FALSE------------------------------------------------------- # readProtoFiles( package = "RProtoBuf" ) ## ----lsproto---------------------------------------------------------------------------- ls("RProtoBuf:DescriptorPool") ## ----newmsg----------------------------------------------------------------------------- p <- new(tutorial.Person, name = "Romain", id = 1) ## ----modmsg----------------------------------------------------------------------------- p$name p$id p$email <- "francoisromain@free.fr" ## ----modfields-------------------------------------------------------------------------- p[["name"]] <- "Romain Francois" p[[ 2 ]] <- 3 p[[ "email" ]] ## ----msgdisp---------------------------------------------------------------------------- p ## ----writeaschar------------------------------------------------------------------------ cat(as.character(p)) ## ----serial1---------------------------------------------------------------------------- serialize( p, NULL ) ## ----serial2---------------------------------------------------------------------------- tf1 <- tempfile() tf1 serialize( p, tf1 ) readBin(tf1, raw(0), 500) ## ----serial3---------------------------------------------------------------------------- tf2 <- tempfile() con <- file(tf2, open = "wb") serialize(p, con) close(con) readBin(tf2, raw(0), 500) ## ----serial4---------------------------------------------------------------------------- # serialize to a file p$serialize(tf1) # serialize to a binary connection con <- file(tf2, open = "wb") p$serialize(con) close(con) ## ----parse1----------------------------------------------------------------------------- args(read) ## ----parse2----------------------------------------------------------------------------- message <- read(tutorial.Person, tf1) cat(as.character(message)) ## ----parse3----------------------------------------------------------------------------- con <- file(tf2, open = "rb") message <- read(tutorial.Person, con) close(con) cat(as.character(message)) ## ----parse4----------------------------------------------------------------------------- # reading the raw vector payload of the message payload <- readBin(tf1, raw(0), 5000) message <- read( tutorial.Person, payload ) ## ----parse5----------------------------------------------------------------------------- # reading from a file message <- tutorial.Person$read(tf1) # reading from a binary connection con <- file(tf2, open = "rb") message <- tutorial.Person$read(con) close(con) # read from the payload message <- tutorial.Person$read(payload) ## ----classes1, eval=FALSE--------------------------------------------------------------- # str(p) ## ----retrieve--------------------------------------------------------------------------- message <- new(tutorial.Person, name = "foo", email = "foo@bar.com", id = 2, phone = list(new(tutorial.Person.PhoneNumber, number = "+33(0)...", type = "HOME"), new(tutorial.Person.PhoneNumber, number = "+33(0)###", type = "MOBILE") ) ) message$name message$email message[["phone"]] # using the tag number message[[2]] # id ## ----modify----------------------------------------------------------------------------- message <- new(tutorial.Person, name = "foo", id = 2) message$email <- "foo@bar.com" message[["id"]] <- 42 message[[1]] <- "foobar" cat(message$as.character()) ## ----has-------------------------------------------------------------------------------- message <- new(tutorial.Person, name = "foo") message$has("name") message$has("id") message$has("phone") ## ----methodclone------------------------------------------------------------------------ m1 <- new(tutorial.Person, name = "foo") m2 <- m1$clone() m2$email <- "foo@bar.com" cat(as.character(m1)) cat(as.character(m2)) ## ----methodisinit----------------------------------------------------------------------- message <- new(tutorial.Person, name = "foo") message$isInitialized() message$id <- 2 message$isInitialized() ## ----messageserialize1------------------------------------------------------------------ message <- new(tutorial.Person, name = "foo", email = "foo@bar.com", id = 2) tf1 <- tempfile() tf1 message$serialize(tf1) tf2 <- tempfile() tf2 con <- file(tf2, open = "wb") message$serialize(con) close(con) ## ----messageserialize2------------------------------------------------------------------ readBin(tf1, raw(0), 500) readBin(tf2, raw(0), 500) ## ----messageserialize3------------------------------------------------------------------ message$serialize(NULL) ## ----messageclear----------------------------------------------------------------------- message <- new(tutorial.Person, name = "foo", email = "foo@bar.com", id = 2) cat(as.character(message)) message$clear() cat(as.character(message)) message <- new(tutorial.Person, name = "foo", email = "foo@bar.com", id = 2) message$clear("id") cat(as.character(message)) ## ----messagesize------------------------------------------------------------------------ message <- new(tutorial.Person, name = "foo", phone = list(new(tutorial.Person.PhoneNumber, number = "+33(0)...", type = "HOME"), new(tutorial.Person.PhoneNumber, number = "+33(0)###", type = "MOBILE") )) message$size("phone") size( message, "phone") ## ----messagebytesize-------------------------------------------------------------------- message <- new(tutorial.Person, name = "foo", email = "foo@bar.com", id = 2) message$bytesize() bytesize(message) length(message$serialize(NULL)) ## ----messageswap------------------------------------------------------------------------ message <- new(tutorial.Person, name = "foo", phone = list(new(tutorial.Person.PhoneNumber, number = "+33(0)...", type = "HOME" ), new(tutorial.Person.PhoneNumber, number = "+33(0)###", type = "MOBILE" ))) message$swap("phone", 1, 2) cat(as.character(message$phone[[1]])) cat(as.character(message$phone[[2]])) swap(message, "phone", 1, 2) cat(as.character(message$phone[[1]])) cat(as.character(message$phone[[2]])) ## ----messagset-------------------------------------------------------------------------- message <- new(tutorial.Person, name = "foo", phone = list(new(tutorial.Person.PhoneNumber, number = "+33(0)...", type = "HOME"), new(tutorial.Person.PhoneNumber, number = "+33(0)###", type = "MOBILE"))) number <- new(tutorial.Person.PhoneNumber, number = "+33(0)---", type = "WORK") message$set("phone", 1, number) cat(as.character( message)) ## ----messagefetch----------------------------------------------------------------------- message <- new(tutorial.Person, name = "foo", phone = list(new(tutorial.Person.PhoneNumber, number = "+33(0)...", type = "HOME"), new(tutorial.Person.PhoneNumber, number = "+33(0)###", type = "MOBILE" ))) message$fetch("phone", 1) ## ----messageset------------------------------------------------------------------------- if (!exists("protobuf_unittest.TestAllTypes", "RProtoBuf:DescriptorPool")) { unittest.proto.file <- system.file("unitTests", "data", "unittest.proto", package="RProtoBuf") readProtoFiles(file=unittest.proto.file) } ## Test setting a singular extensions. test <- new(protobuf_unittest.TestAllExtensions) test$setExtension(protobuf_unittest.optional_int32_extension, as.integer(1)) ## ----messagegetextension---------------------------------------------------------------- test$getExtension(protobuf_unittest.optional_int32_extension) ## ----messageadd------------------------------------------------------------------------- message <- new(tutorial.Person, name = "foo") phone <- new(tutorial.Person.PhoneNumber, number = "+33(0)...", type = "HOME") message$add("phone", phone) cat(message$toString()) ## ----messagestr------------------------------------------------------------------------- message <- new(tutorial.Person, name = "foo", email = "foo@bar.com", id = 2) message$str() str(message) ## ----messageascharacter----------------------------------------------------------------- message <- new(tutorial.Person, name = "foo", email = "foo@bar.com", id = 2) cat(message$as.character()) cat(as.character(message)) ## ----messagetostring-------------------------------------------------------------------- message <- new(tutorial.Person, name = "foo", email = "foo@bar.com", id = 2) cat(message$toString()) cat(toString( message)) ## ----messageaslist---------------------------------------------------------------------- message <- new(tutorial.Person, name = "foo", email = "foo@bar.com", id = 2) as.list(message) ## ----messageupdate---------------------------------------------------------------------- message <- new(tutorial.Person) update(message, name = "foo", id = 2, email = "foo@bar.com") cat(message$as.character()) ## ----messagedescriptor------------------------------------------------------------------ message <- new(tutorial.Person) message$descriptor() descriptor(message) ## ----messagefiledesc-------------------------------------------------------------------- message <- new(tutorial.Person) message$fileDescriptor() fileDescriptor(message) ## ----extractingdescriptors-------------------------------------------------------------- # field descriptor tutorial.Person$email # enum descriptor tutorial.Person$PhoneType # nested type descriptor tutorial.Person$PhoneNumber # same as tutorial.Person.PhoneNumber ## ----newmethod-------------------------------------------------------------------------- tutorial.Person$new() new(tutorial.Person) ## ----newmethod2------------------------------------------------------------------------- tutorial.Person$new(email = "foo@bar.com") # same as update(tutorial.Person$new(), email = "foo@bar.com") ## ----readmethod------------------------------------------------------------------------- # start by serializing a message message <- new(tutorial.Person.PhoneNumber, type = "HOME", number = "+33(0)....") tf <- tempfile() serialize(message, tf) # now read back the message m <- tutorial.Person.PhoneNumber$read(tf) cat(as.character(m)) m <- read( tutorial.Person.PhoneNumber, tf) cat(as.character(m)) ## ----readasciimethod-------------------------------------------------------------------- # start by generating the ASCII representation of a message text <- as.character(new(tutorial.Person, id=1, name="Murray")) text # Then read the ascii representation in as a new message object. msg <- tutorial.Person$readASCII(text) ## ----ascharactermethod------------------------------------------------------------------ desc <- tutorial.Person cat(desc$toString()) cat(toString(desc)) cat(as.character(tutorial.Person)) ## ----aslisttmethod---------------------------------------------------------------------- tutorial.Person$as.list() ## ----asmessagemethod-------------------------------------------------------------------- tutorial.Person$asMessage() ## ----asfiledescmethod------------------------------------------------------------------- desc <- tutorial.Person desc$fileDescriptor() fileDescriptor(desc) ## ----namemethod------------------------------------------------------------------------- # simple name tutorial.Person$name() # name including scope tutorial.Person$name(full = TRUE) ## ----containingtypemethod--------------------------------------------------------------- tutorial.Person$containing_type() tutorial.Person$PhoneNumber$containing_type() ## ----fieldcountmethod------------------------------------------------------------------- tutorial.Person$field_count() ## ----fieldmethod------------------------------------------------------------------------ tutorial.Person$field(1) ## ----nestedtypecountmethod-------------------------------------------------------------- tutorial.Person$nested_type_count() ## ----nestedtypemethod------------------------------------------------------------------- tutorial.Person$nested_type(1) ## ----enumtypecountmethod---------------------------------------------------------------- tutorial.Person$enum_type_count() ## ----enumtypemethod--------------------------------------------------------------------- tutorial.Person$enum_type(1) ## ----ascharactermethod2----------------------------------------------------------------- cat(as.character(tutorial.Person$PhoneNumber)) ## ----tostringmethod2-------------------------------------------------------------------- cat(tutorial.Person.PhoneNumber$toString()) ## ----asmessagemethod2------------------------------------------------------------------- tutorial.Person$id$asMessage() cat(as.character(tutorial.Person$id$asMessage())) ## ----namemethod2------------------------------------------------------------------------ # simple name. name(tutorial.Person$id) # name including scope. name(tutorial.Person$id, full=TRUE) ## ----filedescriptormethod2-------------------------------------------------------------- fileDescriptor(tutorial.Person$id) tutorial.Person$id$fileDescriptor() ## ----containingtypemethod2-------------------------------------------------------------- containing_type(tutorial.Person$id) tutorial.Person$id$containing_type() ## ----isextensionsmethod2---------------------------------------------------------------- is_extension( tutorial.Person$id ) tutorial.Person$id$is_extension() ## ----numbermethod2---------------------------------------------------------------------- number( tutorial.Person$id ) tutorial.Person$id$number() ## ----typemethod2------------------------------------------------------------------------ type( tutorial.Person$id ) tutorial.Person$id$type() ## ----cpptypemethod2--------------------------------------------------------------------- cpp_type( tutorial.Person$id ) tutorial.Person$id$cpp_type() ## ----labelmethod2----------------------------------------------------------------------- label(tutorial.Person$id) label(tutorial.Person$id, TRUE) tutorial.Person$id$label(TRUE) ## ----isrepeatedmethod2------------------------------------------------------------------ is_repeated( tutorial.Person$id ) tutorial.Person$id$is_repeated() ## ----isrequiredmethod2------------------------------------------------------------------ is_required( tutorial.Person$id ) tutorial.Person$id$is_required() ## ----isoptionalmethod2------------------------------------------------------------------ is_optional(tutorial.Person$id) tutorial.Person$id$is_optional() ## ----hasdefaultvaluemethod2------------------------------------------------------------- has_default_value(tutorial.Person$PhoneNumber$type) has_default_value(tutorial.Person$PhoneNumber$number) ## ----defaultvaluemethod2---------------------------------------------------------------- default_value(tutorial.Person$PhoneNumber$type) default_value(tutorial.Person$PhoneNumber$number) ## ----messagetypemethod2----------------------------------------------------------------- message_type(tutorial.Person$phone) tutorial.Person$phone$message_type() ## ----enumtypemethod2-------------------------------------------------------------------- enum_type(tutorial.Person$PhoneNumber$type) ## ----extractingdescriptors2------------------------------------------------------------- tutorial.Person$PhoneType$WORK name(tutorial.Person$PhoneType$value(number=2)) ## ----aslistmethod3---------------------------------------------------------------------- as.list(tutorial.Person$PhoneType) ## ----ascharactermethod3----------------------------------------------------------------- cat(as.character(tutorial.Person$PhoneType )) ## ----asmessagemethod3------------------------------------------------------------------- tutorial.Person$PhoneType$asMessage() cat(as.character(tutorial.Person$PhoneType$asMessage())) ## ----namemethod3------------------------------------------------------------------------ # simple name. name( tutorial.Person$PhoneType ) # name including scope. name( tutorial.Person$PhoneType, full=TRUE ) ## ----filedescriptormethod3-------------------------------------------------------------- fileDescriptor(tutorial.Person$PhoneType) tutorial.Person$PhoneType$fileDescriptor() ## ----containing_typemethod3------------------------------------------------------------- tutorial.Person$PhoneType$containing_type() ## ----lengthmethod3---------------------------------------------------------------------- length(tutorial.Person$PhoneType) tutorial.Person$PhoneType$length() ## ----hasmethod3------------------------------------------------------------------------- tutorial.Person$PhoneType$has("WORK") tutorial.Person$PhoneType$has("nonexistant") ## ----value_countmethod3----------------------------------------------------------------- value_count(tutorial.Person$PhoneType) tutorial.Person$PhoneType$value_count() ## ----valuemethod3----------------------------------------------------------------------- tutorial.Person$PhoneType$value(1) tutorial.Person$PhoneType$value(name="HOME") tutorial.Person$PhoneType$value(number=1) ## ----numbermethod4---------------------------------------------------------------------- number(tutorial.Person$PhoneType$value(number=2)) ## ----namemethod4------------------------------------------------------------------------ # simple name. name(tutorial.Person$PhoneType$value(number=2)) # name including scope. name(tutorial.Person$PhoneType$value(number=2), full=TRUE) ## ----enum_typemethod4------------------------------------------------------------------- enum_type(tutorial.Person$PhoneType$value(number=2)) ## ----as.charactermethod4---------------------------------------------------------------- cat(as.character(tutorial.Person$PhoneType$value(number=2))) ## ----tostringmethod4-------------------------------------------------------------------- cat(toString(tutorial.Person$PhoneType$value(number=2))) ## ----asmessagemethod4------------------------------------------------------------------- tutorial.Person$PhoneType$value(number=2)$asMessage() cat(as.character(tutorial.Person$PhoneType$value(number=2)$asMessage())) ## ----filedescriptorssubsection---------------------------------------------------------- f <- tutorial.Person$fileDescriptor() f f$Person ## ----as.charactermethod5---------------------------------------------------------------- cat(as.character(fileDescriptor(tutorial.Person))) ## ----tostringmethod5-------------------------------------------------------------------- cat(fileDescriptor(tutorial.Person)$toString()) ## ----asmessagemethod5------------------------------------------------------------------- asMessage(tutorial.Person$fileDescriptor()) cat(as.character(asMessage(tutorial.Person$fileDescriptor()))) ## ----as.listmethod5--------------------------------------------------------------------- as.list(tutorial.Person$fileDescriptor()) ## ----namemethod5------------------------------------------------------------------------ name(tutorial.Person$fileDescriptor()) tutorial.Person$fileDescriptor()$name(TRUE) ## ----packagemethod5--------------------------------------------------------------------- tutorial.Person$fileDescriptor()$package() ## ----coerceobjectstomessage------------------------------------------------------------- # coerce a message type descriptor to a message asMessage(tutorial.Person) # coerce a enum descriptor asMessage(tutorial.Person.PhoneType) # coerce a field descriptor asMessage(tutorial.Person$email) # coerce a file descriptor asMessage(fileDescriptor(tutorial.Person)) ## ----identical-------------------------------------------------------------------------- m1 <- new(tutorial.Person, email = "foo@bar.com", id = 2) m2 <- update(new(tutorial.Person) , email = "foo@bar.com", id = 2) identical(m1, m2) ## ----equalforidentical------------------------------------------------------------------ m1 == m2 m1 != m2 ## ----merge------------------------------------------------------------------------------ m1 <- new(tutorial.Person, name = "foobar") m2 <- new(tutorial.Person, email = "foo@bar.com") m3 <- merge(m1, m2) cat(as.character(m3)) ## ----P---------------------------------------------------------------------------------- P("tutorial.Person") new(P("tutorial.Person")) # but we can do this instead tutorial.Person new(tutorial.Person) ## ----64bitex---------------------------------------------------------------------------- 2^53 == (2^53 + 1) ## ----64bitex2, echo=FALSE--------------------------------------------------------------- if (!exists("protobuf_unittest.TestAllTypes", "RProtoBuf:DescriptorPool")) { unittest.proto.file <- system.file("unitTests", "data", "unittest.proto", package="RProtoBuf") readProtoFiles(file=unittest.proto.file) } ## ----groupsfeature---------------------------------------------------------------------- test <- new(protobuf_unittest.TestAllTypes) test$optionalgroup$a <- 3 test$optionalgroup$a cat(as.character(test)) RProtoBuf/inst/opencpu/0000755000176200001440000000000013005133352014555 5ustar liggesusersRProtoBuf/inst/opencpu/ocpu-rpc.py0000644000176200001440000000206013005133352016655 0ustar liggesusers#!/usr/bin/env python # Jeroen Ooms # # HTTPS+ProtoBuf RPC POC using OpenCPU # The call below maps to: do.call(stats::rnorm, list(n=42, mean=100)) import urllib2; from rexp_pb2 import *; #create the post payload, i.e. list(n=42, mean=100) payload = REXP( rclass = 5, rexpValue = [ REXP(rclass = 2, realValue = [42]), REXP(rclass = 2, realValue = [100]) ], attrName = [ "names" ], attrValue = [ REXP(rclass = 0, stringValue = [STRING(strval="n"), STRING(strval="mean")]) ] ); #HTTP POST req = urllib2.Request( 'https://public.opencpu.org/ocpu/library/stats/R/rnorm/pb', data = payload.SerializeToString(), headers = { 'Content-type': 'application/x-protobuf' } ); res = urllib2.urlopen(req); #parse output pb msg = REXP(); msg.ParseFromString(res.read()); #the return value is a double vector in this case print(msg.realValue); ##### To debug: #f = open("payload.msg", "wb") #f.write(payload.SerializeToString()) #f.close() # # Then do in R do: # library(RProtoBuf) # payload <- unserialize_pb("payload.msg") # do.call(stats::rnorm, payload)RProtoBuf/inst/opencpu/ocpu-rpc.R0000644000176200001440000000116113005133352016427 0ustar liggesusers# Jeroen Ooms # # HTTPS+ProtoBuf RPC POC using OpenCPU # The call below maps to: do.call(stats::rnorm, list(n=42, mean=100)) # !! This requires httr (>= 0.2.99). Version 0.2 has a bug. # library(devtools) # install_github("httr") # Actual code library(RProtoBuf) library(httr) args <- list(n=42, mean=100) payload <- serialize_pb(args, NULL) req <- POST ( url = "https://public.opencpu.org/ocpu/library/stats/R/rnorm/pb", body = payload, add_headers( "Content-Type" = "application/x-protobuf" ) ) #This is the output of stats::rnorm(n=42, mean=100) output <- unserialize_pb(req$content) print(length(output)) RProtoBuf/inst/opencpu/ocpu-getdata.R0000644000176200001440000000044213005133352017255 0ustar liggesusers# Jeroen Ooms # # HTTPS+ProtoBuf RPC POC using OpenCPU # Script below downloads MASS::Animals using protobuf library(RProtoBuf) library(httr) req <- GET ('https://public.opencpu.org/ocpu/library/MASS/data/Animals/pb') output <- unserialize_pb(req$content) identical(output, MASS::Animals) RProtoBuf/inst/opencpu/ocpu-getdata.py0000644000176200001440000000065213005133352017507 0ustar liggesusers#!/usr/bin/env python # Jeroen Ooms # # HTTPS+ProtoBuf RPC POC using OpenCPU # Script below downloads MASS::Animals using protobuf import urllib2; from rexp_pb2 import *; #HTTP GET req = urllib2.Request('https://public.opencpu.org/ocpu/library/MASS/data/Animals/pb'); res = urllib2.urlopen(req); #parse output pb msg = REXP(); msg.ParseFromString(res.read()); #the return value is a double vector in this case print(msg); RProtoBuf/inst/opencpu/readme.txt0000644000176200001440000000017313005133352016554 0ustar liggesusersThese scripts illustrate how protocol buffers can be used as a data interchange format or as the basis of an RPC protocol. RProtoBuf/inst/opencpu/rexp_pb2.py0000644000176200001440000002350413005133352016654 0ustar liggesusers# Generated by the protocol buffer compiler. DO NOT EDIT! from google.protobuf import descriptor from google.protobuf import message from google.protobuf import reflection from google.protobuf import descriptor_pb2 # @@protoc_insertion_point(imports) DESCRIPTOR = descriptor.FileDescriptor( name='rexp.proto', package='rexp', serialized_pb='\n\nrexp.proto\x12\x04rexp\"\xb3\x03\n\x04REXP\x12!\n\x06rclass\x18\x01 \x02(\x0e\x32\x11.rexp.REXP.RClass\x12\x15\n\trealValue\x18\x02 \x03(\x01\x42\x02\x10\x01\x12\x14\n\x08intValue\x18\x03 \x03(\x11\x42\x02\x10\x01\x12)\n\x0c\x62ooleanValue\x18\x04 \x03(\x0e\x32\x13.rexp.REXP.RBOOLEAN\x12!\n\x0bstringValue\x18\x05 \x03(\x0b\x32\x0c.rexp.STRING\x12\x10\n\x08rawValue\x18\x06 \x01(\x0c\x12!\n\x0c\x63omplexValue\x18\x07 \x03(\x0b\x32\x0b.rexp.CMPLX\x12\x1d\n\trexpValue\x18\x08 \x03(\x0b\x32\n.rexp.REXP\x12\x10\n\x08\x61ttrName\x18\x0b \x03(\t\x12\x1d\n\tattrValue\x18\x0c \x03(\x0b\x32\n.rexp.REXP\"f\n\x06RClass\x12\n\n\x06STRING\x10\x00\x12\x07\n\x03RAW\x10\x01\x12\x08\n\x04REAL\x10\x02\x12\x0b\n\x07\x43OMPLEX\x10\x03\x12\x0b\n\x07INTEGER\x10\x04\x12\x08\n\x04LIST\x10\x05\x12\x0b\n\x07LOGICAL\x10\x06\x12\x0c\n\x08NULLTYPE\x10\x07\" \n\x08RBOOLEAN\x12\x05\n\x01\x46\x10\x00\x12\x05\n\x01T\x10\x01\x12\x06\n\x02NA\x10\x02\"-\n\x06STRING\x12\x0e\n\x06strval\x18\x01 \x01(\t\x12\x13\n\x04isNA\x18\x02 \x01(\x08:\x05\x66\x61lse\"&\n\x05\x43MPLX\x12\x0f\n\x04real\x18\x01 \x01(\x01:\x01\x30\x12\x0c\n\x04imag\x18\x02 \x02(\x01\x32(\n\x04ocpu\x12 \n\x06\x64oCall\x12\n.rexp.REXP\x1a\n.rexp.REXP') _REXP_RCLASS = descriptor.EnumDescriptor( name='RClass', full_name='rexp.REXP.RClass', filename=None, file=DESCRIPTOR, values=[ descriptor.EnumValueDescriptor( name='STRING', index=0, number=0, options=None, type=None), descriptor.EnumValueDescriptor( name='RAW', index=1, number=1, options=None, type=None), descriptor.EnumValueDescriptor( name='REAL', index=2, number=2, options=None, type=None), descriptor.EnumValueDescriptor( name='COMPLEX', index=3, number=3, options=None, type=None), descriptor.EnumValueDescriptor( name='INTEGER', index=4, number=4, options=None, type=None), descriptor.EnumValueDescriptor( name='LIST', index=5, number=5, options=None, type=None), descriptor.EnumValueDescriptor( name='LOGICAL', index=6, number=6, options=None, type=None), descriptor.EnumValueDescriptor( name='NULLTYPE', index=7, number=7, options=None, type=None), ], containing_type=None, options=None, serialized_start=320, serialized_end=422, ) _REXP_RBOOLEAN = descriptor.EnumDescriptor( name='RBOOLEAN', full_name='rexp.REXP.RBOOLEAN', filename=None, file=DESCRIPTOR, values=[ descriptor.EnumValueDescriptor( name='F', index=0, number=0, options=None, type=None), descriptor.EnumValueDescriptor( name='T', index=1, number=1, options=None, type=None), descriptor.EnumValueDescriptor( name='NA', index=2, number=2, options=None, type=None), ], containing_type=None, options=None, serialized_start=424, serialized_end=456, ) _REXP = descriptor.Descriptor( name='REXP', full_name='rexp.REXP', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ descriptor.FieldDescriptor( name='rclass', full_name='rexp.REXP.rclass', index=0, number=1, type=14, cpp_type=8, label=2, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), descriptor.FieldDescriptor( name='realValue', full_name='rexp.REXP.realValue', index=1, number=2, type=1, cpp_type=5, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=descriptor._ParseOptions(descriptor_pb2.FieldOptions(), '\020\001')), descriptor.FieldDescriptor( name='intValue', full_name='rexp.REXP.intValue', index=2, number=3, type=17, cpp_type=1, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=descriptor._ParseOptions(descriptor_pb2.FieldOptions(), '\020\001')), descriptor.FieldDescriptor( name='booleanValue', full_name='rexp.REXP.booleanValue', index=3, number=4, type=14, cpp_type=8, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), descriptor.FieldDescriptor( name='stringValue', full_name='rexp.REXP.stringValue', index=4, number=5, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), descriptor.FieldDescriptor( name='rawValue', full_name='rexp.REXP.rawValue', index=5, number=6, type=12, cpp_type=9, label=1, has_default_value=False, default_value="", message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), descriptor.FieldDescriptor( name='complexValue', full_name='rexp.REXP.complexValue', index=6, number=7, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), descriptor.FieldDescriptor( name='rexpValue', full_name='rexp.REXP.rexpValue', index=7, number=8, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), descriptor.FieldDescriptor( name='attrName', full_name='rexp.REXP.attrName', index=8, number=11, type=9, cpp_type=9, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), descriptor.FieldDescriptor( name='attrValue', full_name='rexp.REXP.attrValue', index=9, number=12, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), ], extensions=[ ], nested_types=[], enum_types=[ _REXP_RCLASS, _REXP_RBOOLEAN, ], options=None, is_extendable=False, extension_ranges=[], serialized_start=21, serialized_end=456, ) _STRING = descriptor.Descriptor( name='STRING', full_name='rexp.STRING', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ descriptor.FieldDescriptor( name='strval', full_name='rexp.STRING.strval', index=0, number=1, type=9, cpp_type=9, label=1, has_default_value=False, default_value=unicode("", "utf-8"), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), descriptor.FieldDescriptor( name='isNA', full_name='rexp.STRING.isNA', index=1, number=2, type=8, cpp_type=7, label=1, has_default_value=True, default_value=False, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), ], extensions=[ ], nested_types=[], enum_types=[ ], options=None, is_extendable=False, extension_ranges=[], serialized_start=458, serialized_end=503, ) _CMPLX = descriptor.Descriptor( name='CMPLX', full_name='rexp.CMPLX', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ descriptor.FieldDescriptor( name='real', full_name='rexp.CMPLX.real', index=0, number=1, type=1, cpp_type=5, label=1, has_default_value=True, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), descriptor.FieldDescriptor( name='imag', full_name='rexp.CMPLX.imag', index=1, number=2, type=1, cpp_type=5, label=2, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), ], extensions=[ ], nested_types=[], enum_types=[ ], options=None, is_extendable=False, extension_ranges=[], serialized_start=505, serialized_end=543, ) _REXP.fields_by_name['rclass'].enum_type = _REXP_RCLASS _REXP.fields_by_name['booleanValue'].enum_type = _REXP_RBOOLEAN _REXP.fields_by_name['stringValue'].message_type = _STRING _REXP.fields_by_name['complexValue'].message_type = _CMPLX _REXP.fields_by_name['rexpValue'].message_type = _REXP _REXP.fields_by_name['attrValue'].message_type = _REXP _REXP_RCLASS.containing_type = _REXP; _REXP_RBOOLEAN.containing_type = _REXP; DESCRIPTOR.message_types_by_name['REXP'] = _REXP DESCRIPTOR.message_types_by_name['STRING'] = _STRING DESCRIPTOR.message_types_by_name['CMPLX'] = _CMPLX class REXP(message.Message): __metaclass__ = reflection.GeneratedProtocolMessageType DESCRIPTOR = _REXP # @@protoc_insertion_point(class_scope:rexp.REXP) class STRING(message.Message): __metaclass__ = reflection.GeneratedProtocolMessageType DESCRIPTOR = _STRING # @@protoc_insertion_point(class_scope:rexp.STRING) class CMPLX(message.Message): __metaclass__ = reflection.GeneratedProtocolMessageType DESCRIPTOR = _CMPLX # @@protoc_insertion_point(class_scope:rexp.CMPLX) # @@protoc_insertion_point(module_scope) RProtoBuf/inst/unitTests/0000755000176200001440000000000013144106760015115 5ustar liggesusersRProtoBuf/inst/unitTests/runit.FieldDescriptor.R0000644000176200001440000000633413005133352021461 0ustar liggesusers# Copyright 2012 Google Inc. # Author: Murray Stokely # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # this is executed before each test function .setUp <- function(){ if( !exists("tutorial.Person", "RProtoBuf:DescriptorPool")) { protofile <- system.file("proto", "addressbook.proto", package = "RProtoBuf" ) readProtoFiles(file = protofile) } } test.FieldDescriptor.class <- function() { Person <- P( "tutorial.Person") ## field descriptor object checkTrue(!is.null(Person$email), msg="non-null email") ## debug string checkTrue(nchar(as.character( Person$email )) > 1, msg="non-empty email") ## default values checkTrue(!has_default_value(Person$id), msg="no default for id") checkTrue(has_default_value(Person$PhoneNumber$type), msg="default for phone") checkEquals(default_value(Person$PhoneNumber$type), 1, msg="check default for phone type") checkEquals(default_value(Person$id), 0, msg="check default for person id") ## Get the types of field descriptors checkEquals(type(Person$id), TYPE_INT32, msg="type int32") checkEquals(type(Person$id, TRUE), "TYPE_INT32", msg="type int32 as char") checkEquals(cpp_type(Person$email), CPPTYPE_STRING, msg="cpptype string") checkEquals(cpp_type(Person$email, TRUE), "CPPTYPE_STRING", msg="cpptype string as char") ## Get the label of a field descriptor checkEquals(label(Person$id), LABEL_REQUIRED, msg="label required") checkEquals(label(Person$id, TRUE), "LABEL_REQUIRED", msg="label required as char") checkEquals(label(Person$email), LABEL_OPTIONAL, msg="label optional") checkEquals(label(Person$email, TRUE), "LABEL_OPTIONAL", msg="label optional as char") ## Test if a field is optional checkTrue(is_required(Person$id), msg="id is required") checkTrue(!is_optional(Person$id), msg="id is not optional") checkTrue(!is_repeated(Person$id), msg="id is not repeated") checkTrue(!is_required(Person$email), msg="email is not required") checkTrue(is_optional(Person$email), msg="email is optional") checkTrue(!is_repeated(Person$email), msg="email is not repeated") ## Return the class of a message field checkTrue(inherits(message_type(Person$phone), "Descriptor"), msg="inherits Descriptor") ## Containing type of a field is the message descriptor checkTrue(inherits(Person$id$containing_type(), "Descriptor"), msg="inherits containing type Descriptor") ## No containing type for the top-level message descriptor. checkTrue(is.null(Person$containing_type()), msg="no containing typw") } RProtoBuf/inst/unitTests/runit.int32.R0000644000176200001440000000373513005133352017340 0ustar liggesusers# Copyright 2013 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. test.int32 <- function() { if (!exists("protobuf_unittest.TestAllTypes", "RProtoBuf:DescriptorPool")) { unittest.proto.file <- system.file("unitTests", "data", "unittest.proto", package="RProtoBuf") readProtoFiles(file=unittest.proto.file) } a <- new(protobuf_unittest.TestAllTypes) a$repeated_int32 <- 1 # Verify we can set character strings a$repeated_int32 <- c("9007", "9008") checkEquals(length(a$repeated_int32), 2) # Verify we can't set any garbage string to a repeated int32. checkException(a$repeated_int32 <-c("invalid", "invalid")) checkException(a$repeated_int32 <-c("33-")) a$optional_int32 <- 1 a$optional_int32 <- "2" checkEquals(a$optional_int32, 2) # Verify we can't set any garbage string to an optional int32. checkException(a$optional_int32 <- "invalid") a$optional_uint32 <- 10000 a$optional_uint32 <- "200000" checkEquals(a$optional_uint32, 200000) # Verify we can't set any garbage string to an optional uint32. checkException(a$optional_uint32 <- "invalid") a$repeated_uint32 <- c("9007", "9008") checkEquals(length(a$repeated_uint32), 2) } RProtoBuf/inst/unitTests/runit.addressbook.R0000644000176200001440000000773313005133352020703 0ustar liggesusers ## created as ## demo(addressbook) ## creates 'book' ## serialize(book, "/tmp/addressbook.pb") # this is executed before each test function -- but somehow does not work .setUp <- function() { file <- system.file( "examples", "addressbook.pb", package = "RProtoBuf" ) book <- read( tutorial.AddressBook, file ) assign("book", book, globalenv()) } test.size <- function() { checkEquals(book$size("person"), 2, msg="Number of persons") checkEquals(bytesize(book), 125, msg="Bytes in book") checkEquals(bytesize(book$person[[1]]), 60, msg="Bytes of first person message") } test.fileDescriptor <- function() { checkEquals(name(book$fileDescriptor()), "addressbook.proto") } test.personOne <- function() { checkEquals(book$person[[1]]$name, "Romain Francois", msg="First person name") checkEquals(book$person[[2]]$name, "Dirk Eddelbuettel", msg="First person name") checkEquals(book$person[[1]]$id, 1, msg="First person id") checkEquals(book$person[[2]]$id, 2, msg="First person id") checkEquals(book$person[[1]]$email, "romain@r-enthusiasts.com", msg="First person email") checkEquals(book$person[[2]]$email, "edd@debian.org", msg="Second person email") checkEquals(length(book$person[[1]]$phone), 1, msg="First person phones") checkEquals(length(book$person[[2]]$phone), 2, msg="Second person phones") checkEquals(book$person[[1]]$phone[[1]]$number, "+33(0)...", msg="First person phone number") checkEquals(book$person[[2]]$phone[[1]]$number, "+01...", msg="Second person phone number") checkEquals(book$person[[2]]$phone[[1]]$type, 0, msg="Second person phone number") } test.ascii <- function() { # Output in text format to a temporary file out.file <- tempfile() writeLines( as.character(book), file(out.file)) # Verify that we can read back in the message from a text file. book2 <- readASCII( tutorial.AddressBook, file(out.file, "rb")) checkEquals(as.character(book), as.character(book2) ) # Verify that we can read in messages from unopened connections. book3 <- readASCII( tutorial.AddressBook, file(out.file)) checkEquals(as.character(book), as.character(book3) ) # Verify that we get an exception if we try to read from a text connection. # (better than silently getting an empty proto.) book4 <- checkException( readASCII( tutorial.AddressBook, file(out.file, "rt"))) ## # Test does not work on windows because of chmod ## if(!grepl("mingw", R.Version()$platform)){ ## # Verify that we get an exception if the file is not readable. ## old.mode <- file.info(out.file)[["mode"]] ## Sys.chmod(out.file, "0000") ## book5 <- checkException( readASCII( tutorial.AddressBook, file(out.file, "rb"))) ## # Set the permissions back to ensure the file is cleaned up properly. ## Sys.chmod(out.file, old.mode) ## } # Verify that we get an exception if the file is not parseable. out.file2 <- tempfile() writeLines("jibberish", file(out.file2)) book6 <- checkException( readASCII( tutorial.AddressBook, file(out.file2))) # Verify that we get an exception if we forget the file() and thus treat the # path as a protobuf string. checkException( readASCII( tutorial.AddressBook, out.file2)) incomplete.msg <- new(tutorial.Person, name="Murray", email="murray@stokely.org") tmp.file <- tempfile() writeLines(as.character(incomplete.msg), file(tmp.file)) checkTrue(!incomplete.msg$isInitialized()) # Verify we normally get an exception if we try to read an incomplete ASCII protocol buffer checkException( tutorial.Person$readASCII(file(tmp.file))) # Verify we can however read it if we set partial=TRUE. new.msg <- tutorial.Person$readASCII(file(tmp.file), TRUE) checkEquals(incomplete.msg$name, new.msg$name) } RProtoBuf/inst/unitTests/runit.extremevalues.R0000644000176200001440000000352113005133352021263 0ustar liggesusers# Copyright 2013 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. test.uint32 <- function() { if (!exists("protobuf_unittest.TestAllTypes", "RProtoBuf:DescriptorPool")) { unittest.proto.file <- system.file("unitTests", "data", "unittest.proto", package="RProtoBuf") readProtoFiles(file=unittest.proto.file) } foo <- new(protobuf_unittest.TestAllTypes) foo$optional_uint32 <- 2^32 - 1 foo$repeated_uint32 <- c(foo$optional_uint32, foo$optional_uint32) checkEquals(as.character(foo$optional_uint32), "4294967295") checkEquals(foo$optional_uint32, foo$repeated_uint32[[1]]) foo$add("repeated_uint32", c(2^32 - 1, 2^32 - 1)) checkEquals(length(unique(foo$repeated_uint32)), 1) # fixed32 are a more efficient representation of uint32 foo$optional_fixed32 <- 2^32 - 1 foo$repeated_fixed32 <- c(foo$optional_fixed32, foo$optional_fixed32) checkEquals(as.character(foo$optional_fixed32), "4294967295") checkEquals(foo$optional_fixed32, foo$repeated_fixed32[[1]]) } RProtoBuf/inst/unitTests/runit.serialize_pb.R0000644000176200001440000000247513005133352021051 0ustar liggesusers#Jeroen Ooms test.serialize_pb <- function() { #verify that rexp.proto is loaded RProtoBuf:::pb(rexp.REXP) #serialize a nested list x <- list(foo=cars, bar=Titanic) checkEquals(unserialize_pb(serialize_pb(x, NULL)), x) #a bit of everything, copied from jsonlite package set.seed('123') myobject <- list( mynull = NULL, mycomplex = lapply(eigen(matrix(-rnorm(9),3)), round, 3), mymatrix = round(matrix(rnorm(9), 3),3), myint = as.integer(c(1,2,3)), mydf = cars, mylist = list(foo='bar', 123, NA, NULL, list('test')), mylogical = c(TRUE,FALSE,NA), mychar = c('foo', NA, 'bar'), myemptychar = character(0), somemissings = c(1,2,NA,NaN,5, Inf, 7 -Inf, 9, NA), myrawvec = charToRaw('This is a test'), myS4 = asS4("test") ); checkEquals(unserialize_pb(serialize_pb(myobject, NULL)), myobject) } test.serialize_pb.alldatasets <- function() { datasets <- as.data.frame(data(package="datasets")$results) datasets$name <- sub("\\s+.*$", "", datasets$Item) encoded.datasets <- sapply(datasets$name, function(x) serialize_pb(get(x), NULL)) unserialized.datasets <- sapply(encoded.datasets, unserialize_pb) checkTrue(all(sapply(names(unserialized.datasets), function(name) identical(get(name), unserialized.datasets[[name]])))) } RProtoBuf/inst/unitTests/runit.serialize.R0000644000176200001440000000654613005133352020373 0ustar liggesusers# -*- indent-tabs-mode: nil; tab-width: 4; show-trailing-whitespace: t; c-indent-level: 4; c-basic-offset: 4; -*- # Copyright 2012 Google Inc. All Rights Reserved. # Author: Murray Stokely # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # this is executed before each test function .setUp <- function() { if (!exists("tutorial.Person", "RProtoBuf:DescriptorPool")) { protofile <- system.file("proto", "addressbook.proto", package = "RProtoBuf") readProtoFiles(file = protofile) } } test.arrayinputstream <- function() { # Note: This class is experimental, and some parts of the design # may need to change, but this works now. stream <- ArrayInputStream(as.raw(0:10)) checkEquals(stream$ReadRaw(5), as.raw(0:4)) stringstream <- ArrayInputStream(as.raw(c(0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67))) checkEquals(stringstream$ReadString(as.integer(7)), "testing") intstream <- ArrayInputStream(as.raw(c(0x9e, 0xa7, 0x05))) checkEquals(intstream$ReadVarint32(), 86942) } test.encoding <- function() { if (!exists("protobuf_encoding_test.Test1", "RProtoBuf:DescriptorPool")) { unittest.proto.file <- system.file("unitTests", "data", "encoding.proto", package="RProtoBuf") readProtoFiles(file=unittest.proto.file) } # Encoding examples from: # https://developers.google.com/protocol-buffers/docs/encoding test1 <- new(protobuf_encoding_test.Test1) test1$a <- 150 checkIdentical(test1$serialize(NULL), as.raw(c(0x08,0x96,0x01))) test2 <- new(protobuf_encoding_test.Test2) test2$b <- "testing" checkIdentical(test2$serialize(NULL), as.raw(c(0x12, 0x07, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67))) test3 <- new(protobuf_encoding_test.Test3) test3$c$a <- 150 checkIdentical(test3$serialize(NULL), as.raw(c(0x1a, 0x03, 0x08, 0x96, 0x01))) test4 <- new(protobuf_encoding_test.Test4) test4$d <- c(3, 270, 86942) checkIdentical(test4$serialize(NULL), as.raw(c(0x22, 0x06, 0x03, 0x8e, 0x02, 0x9e, 0xa7, 0x05))) } test.serialize <- function() { person <- new(tutorial.Person) checkTrue(!person$isInitialized()) checkException(serialize(person, NULL), "Uninitialized object should fail to serialize.") person$id <- 1 checkException(serialize(person, NULL), "Uninitialized object should fail to serialize.") person$name <- "Murray" checkTrue(person$isInitialized()) checkTrue(length(serialize(person, NULL)) > 1) } RProtoBuf/inst/unitTests/data/0000755000176200001440000000000013037255745016037 5ustar liggesusersRProtoBuf/inst/unitTests/data/nested.proto0000644000176200001440000000024013005133352020362 0ustar liggesusers// mark as Protocol Buffers v2 format syntax = "proto2"; message NestedInner { required int32 x = 1; } message NestedOuter { required NestedInner b = 1; } RProtoBuf/inst/unitTests/data/int64.ascii0000644000176200001440000000010213005133352017766 0ustar liggesusersrepeated_int64: 9007199254740992 repeated_int64: 9007199254740993 RProtoBuf/inst/unitTests/data/unittest.proto0000644000176200001440000005037313005133352020773 0ustar liggesusers// Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. // http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Author: kenton@google.com (Kenton Varda) // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. // // A proto file we will use for unit testing. // mark as Protocol Buffers v2 format syntax = "proto2"; // (Romain Francois) The only thing I have changed in this // file is this import directive. RProtoBuf will import // the extra file from the directory in which this file is import "unittest_import.proto"; // We don't put this in a package within proto2 because we need to make sure // that the generated code doesn't depend on being in the proto2 namespace. // In test_util.h we do "using namespace unittest = protobuf_unittest". package protobuf_unittest; // Protos optimized for SPEED use a strict superset of the generated code // of equivalent ones optimized for CODE_SIZE, so we should optimize all our // tests for speed unless explicitly testing code size optimization. option optimize_for = SPEED; option java_outer_classname = "UnittestProto"; // This proto includes every type of field in both singular and repeated // forms. message TestAllTypes { message NestedMessage { // The field name "b" fails to compile in proto1 because it conflicts with // a local variable named "b" in one of the generated methods. Doh. // This file needs to compile in proto1 to test backwards-compatibility. optional int32 bb = 1; } enum NestedEnum { FOO = 1; BAR = 2; BAZ = 3; } // Singular optional int32 optional_int32 = 1; optional int64 optional_int64 = 2; optional uint32 optional_uint32 = 3; optional uint64 optional_uint64 = 4; optional sint32 optional_sint32 = 5; optional sint64 optional_sint64 = 6; optional fixed32 optional_fixed32 = 7; optional fixed64 optional_fixed64 = 8; optional sfixed32 optional_sfixed32 = 9; optional sfixed64 optional_sfixed64 = 10; optional float optional_float = 11; optional double optional_double = 12; optional bool optional_bool = 13; optional string optional_string = 14; optional bytes optional_bytes = 15; optional group OptionalGroup = 16 { optional int32 a = 17; } optional NestedMessage optional_nested_message = 18; optional ForeignMessage optional_foreign_message = 19; optional protobuf_unittest_import.ImportMessage optional_import_message = 20; optional NestedEnum optional_nested_enum = 21; optional ForeignEnum optional_foreign_enum = 22; optional protobuf_unittest_import.ImportEnum optional_import_enum = 23; optional string optional_string_piece = 24 [ctype=STRING_PIECE]; optional string optional_cord = 25 [ctype=CORD]; // Repeated repeated int32 repeated_int32 = 31; repeated int64 repeated_int64 = 32; repeated uint32 repeated_uint32 = 33; repeated uint64 repeated_uint64 = 34; repeated sint32 repeated_sint32 = 35; repeated sint64 repeated_sint64 = 36; repeated fixed32 repeated_fixed32 = 37; repeated fixed64 repeated_fixed64 = 38; repeated sfixed32 repeated_sfixed32 = 39; repeated sfixed64 repeated_sfixed64 = 40; repeated float repeated_float = 41; repeated double repeated_double = 42; repeated bool repeated_bool = 43; repeated string repeated_string = 44; repeated bytes repeated_bytes = 45; repeated group RepeatedGroup = 46 { optional int32 a = 47; } repeated NestedMessage repeated_nested_message = 48; repeated ForeignMessage repeated_foreign_message = 49; repeated protobuf_unittest_import.ImportMessage repeated_import_message = 50; repeated NestedEnum repeated_nested_enum = 51; repeated ForeignEnum repeated_foreign_enum = 52; repeated protobuf_unittest_import.ImportEnum repeated_import_enum = 53; repeated string repeated_string_piece = 54 [ctype=STRING_PIECE]; repeated string repeated_cord = 55 [ctype=CORD]; // Singular with defaults optional int32 default_int32 = 61 [default = 41 ]; optional int64 default_int64 = 62 [default = 42 ]; optional uint32 default_uint32 = 63 [default = 43 ]; optional uint64 default_uint64 = 64 [default = 44 ]; optional sint32 default_sint32 = 65 [default = -45 ]; optional sint64 default_sint64 = 66 [default = 46 ]; optional fixed32 default_fixed32 = 67 [default = 47 ]; optional fixed64 default_fixed64 = 68 [default = 48 ]; optional sfixed32 default_sfixed32 = 69 [default = 49 ]; optional sfixed64 default_sfixed64 = 70 [default = -50 ]; optional float default_float = 71 [default = 51.5 ]; optional double default_double = 72 [default = 52e3 ]; optional bool default_bool = 73 [default = true ]; optional string default_string = 74 [default = "hello"]; optional bytes default_bytes = 75 [default = "world"]; optional NestedEnum default_nested_enum = 81 [default = BAR ]; optional ForeignEnum default_foreign_enum = 82 [default = FOREIGN_BAR]; optional protobuf_unittest_import.ImportEnum default_import_enum = 83 [default = IMPORT_BAR]; optional string default_string_piece = 84 [ctype=STRING_PIECE,default="abc"]; optional string default_cord = 85 [ctype=CORD,default="123"]; } // Define these after TestAllTypes to make sure the compiler can handle // that. message ForeignMessage { optional int32 c = 1; } enum ForeignEnum { FOREIGN_FOO = 4; FOREIGN_BAR = 5; FOREIGN_BAZ = 6; } message TestAllExtensions { extensions 1 to max; } extend TestAllExtensions { // Singular optional int32 optional_int32_extension = 1; optional int64 optional_int64_extension = 2; optional uint32 optional_uint32_extension = 3; optional uint64 optional_uint64_extension = 4; optional sint32 optional_sint32_extension = 5; optional sint64 optional_sint64_extension = 6; optional fixed32 optional_fixed32_extension = 7; optional fixed64 optional_fixed64_extension = 8; optional sfixed32 optional_sfixed32_extension = 9; optional sfixed64 optional_sfixed64_extension = 10; optional float optional_float_extension = 11; optional double optional_double_extension = 12; optional bool optional_bool_extension = 13; optional string optional_string_extension = 14; optional bytes optional_bytes_extension = 15; optional group OptionalGroup_extension = 16 { optional int32 a = 17; } optional TestAllTypes.NestedMessage optional_nested_message_extension = 18; optional ForeignMessage optional_foreign_message_extension = 19; optional protobuf_unittest_import.ImportMessage optional_import_message_extension = 20; optional TestAllTypes.NestedEnum optional_nested_enum_extension = 21; optional ForeignEnum optional_foreign_enum_extension = 22; optional protobuf_unittest_import.ImportEnum optional_import_enum_extension = 23; optional string optional_string_piece_extension = 24 [ctype=STRING_PIECE]; optional string optional_cord_extension = 25 [ctype=CORD]; // Repeated repeated int32 repeated_int32_extension = 31; repeated int64 repeated_int64_extension = 32; repeated uint32 repeated_uint32_extension = 33; repeated uint64 repeated_uint64_extension = 34; repeated sint32 repeated_sint32_extension = 35; repeated sint64 repeated_sint64_extension = 36; repeated fixed32 repeated_fixed32_extension = 37; repeated fixed64 repeated_fixed64_extension = 38; repeated sfixed32 repeated_sfixed32_extension = 39; repeated sfixed64 repeated_sfixed64_extension = 40; repeated float repeated_float_extension = 41; repeated double repeated_double_extension = 42; repeated bool repeated_bool_extension = 43; repeated string repeated_string_extension = 44; repeated bytes repeated_bytes_extension = 45; repeated group RepeatedGroup_extension = 46 { optional int32 a = 47; } repeated TestAllTypes.NestedMessage repeated_nested_message_extension = 48; repeated ForeignMessage repeated_foreign_message_extension = 49; repeated protobuf_unittest_import.ImportMessage repeated_import_message_extension = 50; repeated TestAllTypes.NestedEnum repeated_nested_enum_extension = 51; repeated ForeignEnum repeated_foreign_enum_extension = 52; repeated protobuf_unittest_import.ImportEnum repeated_import_enum_extension = 53; repeated string repeated_string_piece_extension = 54 [ctype=STRING_PIECE]; repeated string repeated_cord_extension = 55 [ctype=CORD]; // Singular with defaults optional int32 default_int32_extension = 61 [default = 41 ]; optional int64 default_int64_extension = 62 [default = 42 ]; optional uint32 default_uint32_extension = 63 [default = 43 ]; optional uint64 default_uint64_extension = 64 [default = 44 ]; optional sint32 default_sint32_extension = 65 [default = -45 ]; optional sint64 default_sint64_extension = 66 [default = 46 ]; optional fixed32 default_fixed32_extension = 67 [default = 47 ]; optional fixed64 default_fixed64_extension = 68 [default = 48 ]; optional sfixed32 default_sfixed32_extension = 69 [default = 49 ]; optional sfixed64 default_sfixed64_extension = 70 [default = -50 ]; optional float default_float_extension = 71 [default = 51.5 ]; optional double default_double_extension = 72 [default = 52e3 ]; optional bool default_bool_extension = 73 [default = true ]; optional string default_string_extension = 74 [default = "hello"]; optional bytes default_bytes_extension = 75 [default = "world"]; optional TestAllTypes.NestedEnum default_nested_enum_extension = 81 [default = BAR]; optional ForeignEnum default_foreign_enum_extension = 82 [default = FOREIGN_BAR]; optional protobuf_unittest_import.ImportEnum default_import_enum_extension = 83 [default = IMPORT_BAR]; optional string default_string_piece_extension = 84 [ctype=STRING_PIECE, default="abc"]; optional string default_cord_extension = 85 [ctype=CORD, default="123"]; } message TestNestedExtension { extend TestAllExtensions { // Check for bug where string extensions declared in tested scope did not // compile. optional string test = 1002 [default="test"]; } } // We have separate messages for testing required fields because it's // annoying to have to fill in required fields in TestProto in order to // do anything with it. Note that we don't need to test every type of // required filed because the code output is basically identical to // optional fields for all types. message TestRequired { required int32 a = 1; optional int32 dummy2 = 2; required int32 b = 3; extend TestAllExtensions { optional TestRequired single = 1000; repeated TestRequired multi = 1001; } // Pad the field count to 32 so that we can test that IsInitialized() // properly checks multiple elements of has_bits_. optional int32 dummy4 = 4; optional int32 dummy5 = 5; optional int32 dummy6 = 6; optional int32 dummy7 = 7; optional int32 dummy8 = 8; optional int32 dummy9 = 9; optional int32 dummy10 = 10; optional int32 dummy11 = 11; optional int32 dummy12 = 12; optional int32 dummy13 = 13; optional int32 dummy14 = 14; optional int32 dummy15 = 15; optional int32 dummy16 = 16; optional int32 dummy17 = 17; optional int32 dummy18 = 18; optional int32 dummy19 = 19; optional int32 dummy20 = 20; optional int32 dummy21 = 21; optional int32 dummy22 = 22; optional int32 dummy23 = 23; optional int32 dummy24 = 24; optional int32 dummy25 = 25; optional int32 dummy26 = 26; optional int32 dummy27 = 27; optional int32 dummy28 = 28; optional int32 dummy29 = 29; optional int32 dummy30 = 30; optional int32 dummy31 = 31; optional int32 dummy32 = 32; required int32 c = 33; } message TestRequiredForeign { optional TestRequired optional_message = 1; repeated TestRequired repeated_message = 2; optional int32 dummy = 3; } // Test that we can use NestedMessage from outside TestAllTypes. message TestForeignNested { optional TestAllTypes.NestedMessage foreign_nested = 1; } // TestEmptyMessage is used to test unknown field support. message TestEmptyMessage { } // Like above, but declare all field numbers as potential extensions. No // actual extensions should ever be defined for this type. message TestEmptyMessageWithExtensions { extensions 1 to max; } // Test that really large tag numbers don't break anything. message TestReallyLargeTagNumber { // The largest possible tag number is 2^28 - 1, since the wire format uses // three bits to communicate wire type. optional int32 a = 1; optional int32 bb = 268435455; } message TestRecursiveMessage { optional TestRecursiveMessage a = 1; optional int32 i = 2; } // Test that mutual recursion works. message TestMutualRecursionA { optional TestMutualRecursionB bb = 1; } message TestMutualRecursionB { optional TestMutualRecursionA a = 1; optional int32 optional_int32 = 2; } // Test that groups have disjoint field numbers from their siblings and // parents. This is NOT possible in proto1; only proto2. When outputting // proto1, the dup fields should be dropped. message TestDupFieldNumber { optional int32 a = 1; optional group Foo = 2 { optional int32 a = 1; } optional group Bar = 3 { optional int32 a = 1; } } // Needed for a Python test. message TestNestedMessageHasBits { message NestedMessage { repeated int32 nestedmessage_repeated_int32 = 1; repeated ForeignMessage nestedmessage_repeated_foreignmessage = 2; } optional NestedMessage optional_nested_message = 1; } // mstokely commented this out, it breaks with libprotobuf-2.5. // // Test an enum that has multiple values with the same number. // enum TestEnumWithDupValue { // FOO1 = 1; // BAR1 = 2; // BAZ = 3; // FOO2 = 1; // BAR2 = 2; //} // Test an enum with large, unordered values. enum TestSparseEnum { SPARSE_A = 123; SPARSE_B = 62374; SPARSE_C = 12589234; SPARSE_D = -15; SPARSE_E = -53452; SPARSE_F = 0; SPARSE_G = 2; } // Test message with CamelCase field names. This violates Protocol Buffer // standard style. message TestCamelCaseFieldNames { optional int32 PrimitiveField = 1; optional string StringField = 2; optional ForeignEnum EnumField = 3; optional ForeignMessage MessageField = 4; optional string StringPieceField = 5 [ctype=STRING_PIECE]; optional string CordField = 6 [ctype=CORD]; repeated int32 RepeatedPrimitiveField = 7; repeated string RepeatedStringField = 8; repeated ForeignEnum RepeatedEnumField = 9; repeated ForeignMessage RepeatedMessageField = 10; repeated string RepeatedStringPieceField = 11 [ctype=STRING_PIECE]; repeated string RepeatedCordField = 12 [ctype=CORD]; } // We list fields out of order, to ensure that we're using field number and not // field index to determine serialization order. message TestFieldOrderings { optional string my_string = 11; extensions 2 to 10; optional int64 my_int = 1; extensions 12 to 100; optional float my_float = 101; } extend TestFieldOrderings { optional string my_extension_string = 50; optional int32 my_extension_int = 5; } message TestExtremeDefaultValues { optional bytes escaped_bytes = 1 [default = "\0\001\a\b\f\n\r\t\v\\\'\"\xfe"]; optional uint32 large_uint32 = 2 [default = 0xFFFFFFFF]; optional uint64 large_uint64 = 3 [default = 0xFFFFFFFFFFFFFFFF]; optional int32 small_int32 = 4 [default = -0x7FFFFFFF]; optional int64 small_int64 = 5 [default = -0x7FFFFFFFFFFFFFFF]; // The default value here is UTF-8 for "\u1234". (We could also just type // the UTF-8 text directly into this text file rather than escape it, but // lots of people use editors that would be confused by this.) optional string utf8_string = 6 [default = "\341\210\264"]; // Tests for single-precision floating-point values. optional float zero_float = 7 [default = 0]; optional float one_float = 8 [default = 1]; optional float small_float = 9 [default = 1.5]; optional float negative_one_float = 10 [default = -1]; optional float negative_float = 11 [default = -1.5]; // Using exponents optional float large_float = 12 [default = 2E8]; optional float small_negative_float = 13 [default = -8e-28]; } // Test String and Bytes: string is for valid UTF-8 strings message OneString { optional string data = 1; } message OneBytes { optional bytes data = 1; } // Test messages for packed fields message TestPackedTypes { repeated int32 packed_int32 = 90 [packed = true]; repeated int64 packed_int64 = 91 [packed = true]; repeated uint32 packed_uint32 = 92 [packed = true]; repeated uint64 packed_uint64 = 93 [packed = true]; repeated sint32 packed_sint32 = 94 [packed = true]; repeated sint64 packed_sint64 = 95 [packed = true]; repeated fixed32 packed_fixed32 = 96 [packed = true]; repeated fixed64 packed_fixed64 = 97 [packed = true]; repeated sfixed32 packed_sfixed32 = 98 [packed = true]; repeated sfixed64 packed_sfixed64 = 99 [packed = true]; repeated float packed_float = 100 [packed = true]; repeated double packed_double = 101 [packed = true]; repeated bool packed_bool = 102 [packed = true]; repeated ForeignEnum packed_enum = 103 [packed = true]; } message TestPackedExtensions { extensions 1 to max; } extend TestPackedExtensions { repeated int32 packed_int32_extension = 90 [packed = true]; repeated int64 packed_int64_extension = 91 [packed = true]; repeated uint32 packed_uint32_extension = 92 [packed = true]; repeated uint64 packed_uint64_extension = 93 [packed = true]; repeated sint32 packed_sint32_extension = 94 [packed = true]; repeated sint64 packed_sint64_extension = 95 [packed = true]; repeated fixed32 packed_fixed32_extension = 96 [packed = true]; repeated fixed64 packed_fixed64_extension = 97 [packed = true]; repeated sfixed32 packed_sfixed32_extension = 98 [packed = true]; repeated sfixed64 packed_sfixed64_extension = 99 [packed = true]; repeated float packed_float_extension = 100 [packed = true]; repeated double packed_double_extension = 101 [packed = true]; repeated bool packed_bool_extension = 102 [packed = true]; repeated ForeignEnum packed_enum_extension = 103 [packed = true]; } // Test that RPC services work. message FooRequest {} message FooResponse {} service TestService { rpc Foo(FooRequest) returns (FooResponse); rpc Bar(BarRequest) returns (BarResponse); } message BarRequest {} message BarResponse {} RProtoBuf/inst/unitTests/data/unittest_import.proto0000644000176200001440000000473613005133352022367 0ustar liggesusers// Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. // http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Author: kenton@google.com (Kenton Varda) // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. // // A proto file which is imported by unittest.proto to test importing. // mark as Protocol Buffers v2 format syntax = "proto2"; // We don't put this in a package within proto2 because we need to make sure // that the generated code doesn't depend on being in the proto2 namespace. // In test_util.h we do // "using namespace unittest_import = protobuf_unittest_import". package protobuf_unittest_import; option optimize_for = SPEED; // Excercise the java_package option. option java_package = "com.google.protobuf.test"; // Do not set a java_outer_classname here to verify that Proto2 works without // one. message ImportMessage { optional int32 d = 1; } enum ImportEnum { IMPORT_FOO = 7; IMPORT_BAR = 8; IMPORT_BAZ = 9; } RProtoBuf/inst/unitTests/data/bytes.proto0000644000176200001440000000040313005133352020227 0ustar liggesusers// mark as Protocol Buffers v2 format syntax = "proto2"; option optimize_for = SPEED; option java_outer_classname = "BytesProto"; message TestBytes { required bytes req = 1; optional bytes opt = 2 [default = "hello world"]; repeated bytes rep = 3; } RProtoBuf/inst/unitTests/data/proto3.proto0000644000176200001440000000017113037255745020351 0ustar liggesusers syntax = "proto3"; message SearchRequest { string query = 1; int32 page_number = 2; int32 result_per_page = 3; } RProtoBuf/inst/unitTests/data/encoding.proto0000644000176200001440000000054413005133352020675 0ustar liggesusers// mark as Protocol Buffers v2 format syntax = "proto2"; // Examples from: // https://developers.google.com/protocol-buffers/docs/encoding package protobuf_encoding_test; message Test1 { required int32 a = 1; } message Test2 { required string b = 2; } message Test3 { required Test1 c = 3; } message Test4 { repeated int32 d = 4 [packed=true]; } RProtoBuf/inst/unitTests/runit.messages.R0000644000176200001440000000400213005133352020174 0ustar liggesusers# Copyright 2013 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. test.message <- function() { if (!exists("protobuf_unittest.TestAllTypes", "RProtoBuf:DescriptorPool")) { unittest.proto.file <- system.file("unitTests", "data", "unittest.proto", package="RProtoBuf") readProtoFiles(file=unittest.proto.file) } a <- new(protobuf_unittest.TestAllTypes) a$optionalgroup$a <- 3 checkEquals(a$optionalgroup$a, 3) a$repeated_nested_message <- list( new(protobuf_unittest.TestAllTypes.NestedMessage, bb=3), new(protobuf_unittest.TestAllTypes.NestedMessage, bb=4)) checkEquals(a$repeated_nested_message[[1]]$bb, 3) checkEquals(a$repeated_nested_message[[2]]$bb, 4) checkException(a$repeated_nested_message <- list( new(protobuf_unittest.ForeignMessage, c=1), new(protobuf_unittest.TestAllTypes.NestedMessage, bb=4))) checkException(a$repeated_nested_message <- list( new(protobuf_unittest.TestAllTypes.NestedMessage, bb=4), new(protobuf_unittest.ForeignMessage, c=1))) checkException(a$repeated_nested_message <- list( new(protobuf_unittest.TestAllTypes.NestedMessage, bb=4), 3)) checkException(a$repeated_nested_message <- list( new(protobuf_unittest.TestAllTypes.NestedMessage, bb=4), "foo")) } RProtoBuf/inst/unitTests/runit.bool.R0000644000176200001440000000352013005133352017324 0ustar liggesusers# Copyright 2013 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. test.bool <- function() { if (!exists("protobuf_unittest.TestAllTypes", "RProtoBuf:DescriptorPool")) { unittest.proto.file <- system.file("unitTests", "data", "unittest.proto", package="RProtoBuf") readProtoFiles(file=unittest.proto.file) } a <- new(protobuf_unittest.TestAllTypes) a$optional_bool <- TRUE a$optional_bool <- FALSE # Verify we can not set a protocol buffer bool to NA. checkException(a$optional_bool <- NA) # Verify we can set character strings a$repeated_bool <- c(TRUE, FALSE, TRUE) checkEquals(length(unique(a$repeated_bool)), 2) # Verify we can't set any garbage string to a bool. checkException(a$optional_bool <- "100") checkException(a$optional_bool <- "invalid") # Verify we can't set any garbage string to a repeated bool. checkException(a$repeated_bool <-c("invalid", "invalid")) checkException(a$repeated_bool <-c("33-")) # Verify we can set NA checkException(a$repeated_bool <- c(TRUE, FALSE, TRUE, NA)) } RProtoBuf/inst/unitTests/runit.import.R0000644000176200001440000000176013144106760017716 0ustar liggesusers# Copyright 2011 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. test.import <- function() { ## Verify that we get a graceful error rather than a segfault. checkException(readProtoFiles(system.file("DESCRIPTION", package="RProtoBuf"))) } test.assign.in.global <- function() { xx.undef <<- 3 checkEquals(xx.undef, 3) } RProtoBuf/inst/unitTests/runit.enums.R0000644000176200001440000000475513005133352017533 0ustar liggesusers# Copyright 2011 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. test.enums <- function() { ProtoFormat <- P("tutorial.Person") # value(..) returns an EnumValueDescriptor object checkEquals(name(value(ProtoFormat$PhoneType, index=1)), "MOBILE") checkEquals(name(value(ProtoFormat$PhoneType, index=1), TRUE), "tutorial.Person.MOBILE") checkEquals(number(value(ProtoFormat$PhoneType, index=1)), 0) checkTrue(inherits(enum_type(value(ProtoFormat$PhoneType, index=1)), "EnumDescriptor")) checkTrue(inherits(asMessage(value(ProtoFormat$PhoneType, index=1)), "Message")) # Now check the '$' interfaces checkEquals(name(value(ProtoFormat$PhoneType, index=1)), value(ProtoFormat$PhoneType, index=1)$name()) checkEquals(number(value(ProtoFormat$PhoneType, index=1)), value(ProtoFormat$PhoneType, index=1)$number()) checkEquals(name(value(ProtoFormat$PhoneType, index=2)), "HOME") checkEquals(length(ProtoFormat$PhoneType), 3) checkTrue(has(ProtoFormat$PhoneType, "WORK")) checkTrue(!has(ProtoFormat$PhoneType, "NONEXISTANT")) # Verify we can subset the EnumDescriptor class checkEquals(ProtoFormat$PhoneType[["WORK"]], 2) checkEquals(ProtoFormat$PhoneType[["MOBILE"]], 0) # Verify that invalid indices are returned as NULL. checkTrue(is.null(value(ProtoFormat$PhoneType, index=900))) # Verify that we import top-level enums from .proto files. if (!exists("protobuf_unittest.TestAllTypes", "RProtoBuf:DescriptorPool")) { unittest.proto.file <- system.file("unitTests", "data", "unittest.proto", package="RProtoBuf") readProtoFiles(file=unittest.proto.file) } checkTrue(inherits(P("protobuf_unittest.ForeignEnum"), "EnumDescriptor")) } RProtoBuf/inst/unitTests/runit.descriptors.R0000644000176200001440000000241213005133352020731 0ustar liggesusers# Copyright 2014 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. test.descriptor <- function() { checkTrue(inherits(tutorial.Person$email, "FieldDescriptor")) checkTrue(inherits(tutorial.Person[["email"]], "FieldDescriptor")) checkTrue(inherits(tutorial.Person[[1]], "FieldDescriptor")) # Currently, the $ extractor for fields returns NULL for invalid reference # stop() probably better. checkEquals(tutorial.Person$nonexistantfoobarbaz, NULL) # But we raise an error with invalid indices with '[['. checkException(tutorial.Person[[909]]) checkException(tutorial.Person[["nonexistantfoobarbaz"]]) } RProtoBuf/inst/unitTests/runit.int64.R0000644000176200001440000000544113005133352017341 0ustar liggesusers# Copyright 2013 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. test.int64 <- function() { # Preserve option. old.optval <- options("RProtoBuf.int64AsString") on.exit(options(old.optval)) if (!exists("protobuf_unittest.TestAllTypes", "RProtoBuf:DescriptorPool")) { unittest.proto.file <- system.file("unitTests", "data", "unittest.proto", package="RProtoBuf") readProtoFiles(file=unittest.proto.file) } if (.Machine$sizeof.longlong < 8) { warning("Can't test 64-bit int type on platform with sizeof(long long) < 8") return() } if (is.na(Rcpp:::capabilities()["long long"]) || Rcpp:::capabilities()["long long"] != TRUE) { warning("Can't test 64-bit int type without RCPP_LONG_LONG support.") return() } a <- new(protobuf_unittest.TestAllTypes) a$repeated_int64 <- 1 # Now just test that we can use add to set int64 fields. a$add("repeated_int64", 2:10) checkEquals(length(a$repeated_int64), 10) # Verify we can set character strings of large 64-bit ints a$repeated_int64 <- c("9007199254740992", "9007199254740993") checkEquals(length(a$repeated_int64), 2) # Verify we can't set any garbage string to a repeated int64. checkException(a$repeated_int64 <-c("invalid", "invalid")) a$optional_int64 <- 1 a$optional_int64 <- "2" checkEquals(a$optional_int64, 2) # Verify we can't set any garbage string to an optional int64. checkException(a$optional_int64 <- "invalid") a <- protobuf_unittest.TestAllTypes$readASCII( file(system.file("unitTests", "data", "int64.ascii", package="RProtoBuf"))) # And can read them in OK from an ASCII file. checkEquals(length(a$repeated_int64), 2) # By default, when they are read as numerics, only 1 unique value checkEquals(length(unique(a$repeated_int64)), 1) options("RProtoBuf.int64AsString" = TRUE) # But we can see they are different if we treat them as strings. checkEquals(length(unique(a$repeated_int64)), 2) } RProtoBuf/inst/unitTests/runit.proto3.R0000644000176200001440000000307313037255745017642 0ustar liggesusers## rprotobuf.h: R/C++ interface class library ## ## Copyright (C) 2017 - Dirk Eddelbuettel ## ## This file is part of RProtoBuf. ## ## RProtoBuf is free software: you can redistribute it and/or modify it ## under the terms of the GNU General Public License as published by ## the Free Software Foundation, either version 2 of the License, or ## (at your option) any later version. ## ## RProtoBuf is distributed in the hope that it will be useful, but ## WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with RProtoBuf. If not, see . ## The Travis CI tests use both proto2 and proto3, so we need to condition against ## running this one with proto2 where it cannot pass we impose a proto3 file isProto3 <- (RProtoBuf:::getProtobufLibVersion() >= 3000000) if (isProto3) { .setUp <- function(){ if( !exists("SearchRequest", "RProtoBuf:DescriptorPool")) { unitest.proto.file <- system.file("unitTests", "data", "proto3.proto", package="RProtoBuf") readProtoFiles(file = unitest.proto.file) } } test.proto3 <- function() { q <- new(SearchRequest, query="abc", page_number=42L, result_per_page=77L) checkEquals(q$query, "abc", msg="proto3 string") checkEquals(q$page_number, 42L, msg="proto3 int") checkEquals(q$result_per_page, 77L, msg="proto3 int again") } } RProtoBuf/inst/unitTests/runTests.R0000644000176200001440000000354613005133352017070 0ustar liggesuserspkg <- "RProtoBuf" if(require("RUnit", quietly = TRUE)) { library(package=pkg, character.only = TRUE) if(!(exists("path") && file.exists(path))) path <- system.file("unitTests", package = pkg) ## --- Testing --- ## Define tests testSuite <- defineTestSuite(name=paste(pkg, "unit testing"), dirs = path) if(interactive()) { cat("Now have RUnit Test Suite 'testSuite' for package '", pkg, "' :\n", sep='') str(testSuite) cat('', "Consider doing", "\t tests <- runTestSuite(testSuite)", "\nand later", "\t printTextProtocol(tests)", '', sep="\n") } else { ## run from shell / Rscript / R CMD Batch / ... ## Run tests <- runTestSuite(testSuite) if(file.access(path, 02) != 0) { ## cannot write to path -> use writable one tdir <- tempfile(paste(pkg, "unitTests", sep="_")) dir.create(tdir) pathReport <- file.path(tdir, "report") cat("RUnit reports are written into ", tdir, "/report.(txt|html)", sep = "") } else { pathReport <- file.path(path, "report") } ## Print results # printTextProtocol(tests) printTextProtocol(tests, fileName=paste(pathReport, ".txt", sep="")) ## Print HTML version to a file ## printHTMLProtocol has problems on Mac OS X if (Sys.info()["sysname"] != "Darwin") printHTMLProtocol(tests, fileName=paste(pathReport, ".html", sep="")) ## stop() if there are any failures i.e. FALSE to unit test. ## This will cause R CMD check to return error and stop if(getErrors(tests)$nFail > 0) { stop("one of the unit tests failed") } } } else { cat("R package 'RUnit' cannot be loaded -- no unit tests run\n", "for package", pkg,"\n") } RProtoBuf/inst/unitTests/runit.extensions.R0000644000176200001440000000770313005133352020577 0ustar liggesusers# Copyright 2013 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. test.extension <- function() { if (!exists("protobuf_unittest.TestAllTypes", "RProtoBuf:DescriptorPool")) { unittest.proto.file <- system.file("unitTests", "data", "unittest.proto", package="RProtoBuf") readProtoFiles(file=unittest.proto.file) } checkTrue(inherits(protobuf_unittest.optional_uint32_extension, "FieldDescriptor")) # Verify we can pull in other extensions with P() checkTrue(inherits(P("protobuf_unittest.optional_uint32_extension"), "FieldDescriptor")) ## Test setting and getting singular extensions. test <- new(protobuf_unittest.TestAllExtensions) test$setExtension(protobuf_unittest.optional_int32_extension, as.integer(1)) checkEquals(test$getExtension(protobuf_unittest.optional_int32_extension), as.integer(1)) ## Unset extensions should return NULL. checkEquals(test$getExtension(protobuf_unittest.optional_double_extension), NULL) ## Test setting and getting repeated extensions. checkEquals(test$getExtension(protobuf_unittest.repeated_int32_extension), NULL) test$setExtension(protobuf_unittest.repeated_int32_extension, 1:10) checkEquals(test$getExtension(protobuf_unittest.repeated_int32_extension), 1:10) ## Test nested extensions. checkEquals(test$getExtension(protobuf_unittest.TestNestedExtension.test), NULL) test$setExtension(protobuf_unittest.TestNestedExtension.test, "foo") checkEquals(test$getExtension(protobuf_unittest.TestNestedExtension.test), "foo") ## Test setting and getting enums. test$setExtension(protobuf_unittest.optional_nested_enum_extension, protobuf_unittest.TestAllTypes.NestedEnum$BAR) ## Test foreign message extensions foo <- new(protobuf_unittest.ForeignMessage) foo$c <- 3 test$setExtension(protobuf_unittest.optional_foreign_message_extension, foo) checkEquals(test$getExtension(protobuf_unittest.optional_foreign_message_extension)$c, 3) # This causes an Rcpp exception, but not an R stop error as of my # version of Rcpp, so we can't checkError unfortunately, but we # can at least make sure it doesn't crash R. # TODO(edd): Commented out now # test$setExtension(protobuf_unittest.optional_nested_enum_extension, 9) ## Test nested message extensions. tmp <- new( protobuf_unittest.TestAllTypes.NestedMessage ) tmp$bb <- 3 test$setExtension(protobuf_unittest.optional_nested_message_extension, tmp) checkEquals(test$getExtension(protobuf_unittest.optional_nested_message_extension)$bb, 3) ## Check that we do something sensible if invalid field descriptors are passed checkException(test$getExtension(protobuf_unittest.TestAllExtensions)) checkException(test$setExtension(protobuf_unittest.TestAllExtensions, 3)) ## Check that we don't CHECK fail in C++, but instead give a reasonable ## error message if incorrect extensions types are provided. checkException(test$getExtension(protobuf_unittest.my_extension_string)) } RProtoBuf/inst/unitTests/runit.golden.message.R0000644000176200001440000001272013005133352021266 0ustar liggesusers # this is executed before each test function .setUp <- function(){ if( ! exists( "protobuf_unittest_import.TestAllTypes", "RProtoBuf:DescriptorPool" ) ){ unitest.proto.file <- system.file( "unitTests", "data", "unittest.proto", package = "RProtoBuf" ) readProtoFiles( file = unitest.proto.file ) } } .tearDown <- function(){} test.import <- function(){ checkTrue( exists( "protobuf_unittest_import.ImportMessage", "RProtoBuf:DescriptorPool" ) , msg = "exists( protobuf_unittest_import.ImportMessage ) " ) checkTrue( exists( "protobuf_unittest_import.ImportEnum", "RProtoBuf:DescriptorPool" ) , msg = "exists( protobuf_unittest_import.ImportEnum ) " ) checkEquals( names(as.list( protobuf_unittest_import.ImportMessage)), "d", msg = "names( protobuf_unittest_import.ImportMessage ) == 'd'" ) import_enum <- as.list(protobuf_unittest_import.ImportEnum ) checkTrue( all( c("IMPORT_FOO", "IMPORT_BAR", "IMPORT_BAZ") %in% names(import_enum) ), msg = "expected names for 'protobuf_unittest_import.ImportEnum'" ) checkEquals( unlist(unname(import_enum)), 7:9, msg = "expected values for 'protobuf_unittest_import.ImportEnum' " ) } test.readProtoFile <- function(){ checkTrue( exists( "protobuf_unittest.TestAllTypes", "RProtoBuf:DescriptorPool" ), msg = "exists( protobuf_unittest_import.TestAllTypes ) " ) checkTrue( exists( "protobuf_unittest.TestAllTypes.NestedMessage", "RProtoBuf:DescriptorPool" ), msg = "exists( protobuf_unittest_import.TestAllTypes.NestedMessage ) " ) checkTrue( exists( "protobuf_unittest.TestAllTypes.NestedEnum", "RProtoBuf:DescriptorPool" ), msg = "exists( protobuf_unittest_import.TestAllTypes.NestedEnum ) " ) checkTrue( exists( "protobuf_unittest.TestAllTypes.OptionalGroup", "RProtoBuf:DescriptorPool" ) , msg = "exists( protobuf_unittest.TestAllTypes.OptionalGroup ) " ) types <- c("int32", "int64", "uint32", "uint64", "sint32", "sint64", "fixed32", "fixed64", "sfixed32", "sfixed64", "float", "double", "bool", "string", "bytes" ) fieldnames <- names( as.list( protobuf_unittest.TestAllTypes ) ) prefixes <- c("optional", "default", "repeated" ) for( prefix in prefixes ){ for( type in types ){ checkTrue( sprintf( "%s_%s", prefix, type ) %in% fieldnames, msg = sprintf( "%s_%s in field names", prefix, type ) ) } checkTrue( sprintf("%s_foreign_enum" , prefix ) %in% fieldnames, msg = sprintf( "%s_foreign_enum in field names" , prefix ) ) checkTrue( sprintf("%s_import_enum" , prefix ) %in% fieldnames, msg = sprintf( "%s_import_enum in field names" , prefix ) ) } checkTrue( exists( "protobuf_unittest.ForeignMessage", "RProtoBuf:DescriptorPool" ) , msg = "exists( protobuf_unittest.ForeignMessage ) " ) checkEquals( names(as.list(protobuf_unittest.ForeignMessage)), "c" ) checkTrue( exists( "protobuf_unittest.ForeignEnum", "RProtoBuf:DescriptorPool" ) , msg = "exists( protobuf_unittest.ForeignEnum ) " ) foreign_enum <- as.list( protobuf_unittest.ForeignEnum ) checkEquals( length(foreign_enum), 3L, msg = "length( protobuf_unittest.ForeignEnum ) == 3" ) checkTrue( all( c("FOREIGN_FOO", "FOREIGN_BAR", "FOREIGN_BAZ") %in% names( foreign_enum ) ), msg = "expected names for enum `protobuf_unittest.ForeignEnum`" ) checkEquals( unlist(unname(as.list(protobuf_unittest.ForeignEnum))), 4:6, msg = "expected values for enum `protobuf_unittest.ForeignEnum`" ) } # Early versions of RProtoBuf did not support repeated messages properly. test.repeatedFields <- function(){ test <- new(protobuf_unittest.TestAllTypes) test$add("repeated_int32", c(1:5)) checkEquals(test$repeated_int32, c(1:5)) test$repeated_int32 <- 1 checkEquals(test$repeated_int32, 1) # Prior to RProtoBuf v0.2.5, this was not handled properly. test.2 <- new(protobuf_unittest.TestAllTypes, repeated_string=c("foo", "bar")) checkEquals(test.2$repeated_string, c("foo", "bar")) # Versions of RProtoBuf <= 0.2.5 had non-deterministic behavior due to a # memory management bug when setting a repeated field to a # non-vector type (e.g. a Message). test$repeated_foreign_message <- list(new(protobuf_unittest.ForeignMessage, c = 1), new(protobuf_unittest.ForeignMessage, c = 2)) checkEquals(length(test$repeated_foreign_message), 2) test$repeated_foreign_message <- new(protobuf_unittest.ForeignMessage, c = 3) checkEquals(length(test$repeated_foreign_message), 1) } test.repeated.bools <- function() { test <- new(protobuf_unittest.TestAllTypes) test$add("repeated_bool", c(TRUE, FALSE)) checkEquals(test$repeated_bool, c(TRUE, FALSE)) test$add("repeated_bool", as.integer(c(TRUE, FALSE))) test$add("repeated_bool", as.numeric(c(TRUE, FALSE))) checkEquals(test$repeated_bool, rep(c(TRUE, FALSE), 3)) # Verify that we don't silently cast NA into TRUE or FALSE. checkException(test$add("repeated_bool"), c(TRUE, FALSE, NA)) } # Versions of RProtoBuf <= 0.2.5 would terminate the R instance with unhandled Rcpp exceptions. test.invalidAssignments <- function(){ test <- new(protobuf_unittest.TestAllTypes) checkException(test$optional_int32 <- 1:10) } # Versions of RProtoBuf <= 0.2.5 did not distinguish between non-existant # and not-set fields with has(). test.has <- function(){ test <- new(protobuf_unittest.TestAllTypes) test$add("repeated_int32", c(1:5)) checkTrue( has(test, "repeated_int32")) checkTrue( test$has("repeated_int32")) checkTrue( is.null(test$has("nonexistant"))) checkTrue( !test$has("optional_int32")) } RProtoBuf/inst/unitTests/runit.bytes.R0000644000176200001440000000211113005133352017512 0ustar liggesusers .setUp <- function(){ if( ! exists( "TestBytes", "RProtoBuf:DescriptorPool" ) ){ unitest.proto.file <- system.file( "unitTests", "data", "bytes.proto", package = "RProtoBuf" ) readProtoFiles(file = unitest.proto.file) } } test.all <- function() { test <- new(TestBytes, req = "abc", rep = list(charToRaw("def"), raw(10))) checkEquals(rawToChar(test$req), "abc") test$req <- charToRaw("abc") checkEquals(rawToChar(test$req), "abc") checkEquals(rawToChar(test$opt), "hello world") checkEquals(test$rep, list(charToRaw("def"), raw(10))) test$rep[[3]]=charToRaw("ghi") checkEquals(test$rep, list(charToRaw("def"), raw(10), charToRaw("ghi"))) ser <- serialize(test, NULL) test1 <- read(TestBytes, ser) checkEquals(rawToChar(test1$req), "abc") checkEquals(rawToChar(test1$opt), "hello world") checkEquals(test1$rep, list(charToRaw("def"), raw(10), charToRaw("ghi"))) # Test raw(10) can be set to a single req field. test$req <- raw(10) checkEquals(length(test$req), 10) checkTrue(all(test$req == raw(10))) } RProtoBuf/inst/unitTests/runit.nested.R0000644000176200001440000000122113005133352017647 0ustar liggesusers.setUp <- function(){ if( ! exists( "NestedOuter", "RProtoBuf:DescriptorPool" ) ) { ## None of the messages in unittest.proto is exactly right to tickle this bug. unitest.proto.file <- system.file( "unitTests", "data", "nested.proto", package = "RProtoBuf" ) readProtoFiles(file = unitest.proto.file) } } # RProtoBuf before v0.2.5 had a bug whereby uninitialized memory was read and used # to determine whether or not to update a nested message field in new() / update(). test.nested <- function() { for (i in 1:1000) { q <- new(NestedOuter, b=new(NestedInner, x=1)) checkTrue(q$isInitialized()) } } RProtoBuf/inst/proto/0000755000176200001440000000000013005133352014247 5ustar liggesusersRProtoBuf/inst/proto/rexp.proto0000644000176200001440000000243513005133352016316 0ustar liggesusers// Originally written by Saptarshi Guha for RHIPE (http://www.rhipe.org) // Released under Apache License 2.0, and reused with permission here // Extended in November 2014 with new types to support encoding // language, environment, and function types from R. // mark as Protocol Buffers v2 format syntax = "proto2"; package rexp; option java_package = "org.godhuli.rhipe"; option java_outer_classname = "REXPProtos"; // TODO(mstokely): Refine this using the new protobuf 2.6 oneof field // for unions. message REXP { enum RClass { STRING = 0; RAW = 1; REAL = 2; COMPLEX = 3; INTEGER = 4; LIST = 5; LOGICAL = 6; NULLTYPE = 7; NATIVE = 8; } enum RBOOLEAN { F=0; T=1; NA=2; } required RClass rclass = 1; repeated double realValue = 2 [packed=true]; repeated sint32 intValue = 3 [packed=true]; repeated RBOOLEAN booleanValue = 4; repeated STRING stringValue = 5; optional bytes rawValue = 6; repeated CMPLX complexValue = 7; repeated REXP rexpValue = 8; repeated string attrName = 11; repeated REXP attrValue = 12; optional bytes nativeValue = 13; } message STRING { optional string strval = 1; optional bool isNA = 2 [default=false]; } message CMPLX { optional double real = 1 [default=0]; required double imag = 2; } RProtoBuf/inst/proto/addressbook.proto0000644000176200001440000000117413005133352017637 0ustar liggesusers// mark as Protocol Buffers v2 format syntax = "proto2"; package tutorial; option java_package = "com.example.tutorial"; option java_outer_classname = "AddressBookProtos"; message Person { required string name = 1; required int32 id = 2; optional string email = 3; enum PhoneType { MOBILE = 0; HOME = 1; WORK = 2; } message PhoneNumber { required string number = 1; optional PhoneType type = 2 [default = HOME]; } repeated PhoneNumber phone = 4; extensions 100 to 199; } message AddressBook { repeated Person person = 1; } service EchoService { rpc Echo (Person) returns (Person); } RProtoBuf/inst/proto/helloworld.proto0000644000176200001440000000054013005133352017506 0ustar liggesusers// mark as Protocol Buffers v2 format syntax = "proto2"; package rprotobuf; option java_package = "org.rproject.rprotobuf"; option java_outer_classname = "HelloWorld"; message HelloWorldRequest{} message HelloWorldResponse{ required string message = 1; } service HelloWorldService{ rpc HelloWorld(HelloWorldRequest) returns(HelloWorldResponse); } RProtoBuf/configure.ac0000644000176200001440000001022513144561020014416 0ustar liggesusers# -*- mode: autoconf; autoconf-indentation: 4; -*- # # RProtoBuf configure.ac # # Copyright (C) 2009 - 2017 Dirk Eddelbuettel # Portions Copyright (C) 2010 Romain Francois # Portions Copyright (C) 2013 Murray Stokely # Portions Copyright (C) 2016 Craig Radcliffe # require at least autoconf 2.61 AC_PREREQ(2.61) # Process this file with autoconf to produce a configure script. AC_INIT([RProtoBuf],[0.4.10]) # We are using C++ AC_LANG(C++) AC_REQUIRE_CPP AC_PROG_CC AC_PROG_CXX ## simpler alternative to test below: AC_PATH_PROG(PROTOC, protoc) AC_DEFUN([AC_PROG_PKGCONFIG], [AC_CHECK_PROG(PKGCONFIG,pkg-config,yes)]) AC_PROG_PKGCONFIG ## use pkg-config for ProtoBuf settings ## if test x"${PKGCONFIG}" == x"yes"; then if pkg-config --exists protobuf; then protobuf_cxxflags=`pkg-config --cflags protobuf` protobuf_libs=`pkg-config --libs protobuf` else protobuf_cxxflags="" protobuf_libs="-lprotobuf" fi else # Add a reasonable default of -lprotobuf if we don't have pkg-config protobuf_cxxflags="" protobuf_libs="-lprotobuf" fi ## And make sure these flags are used for the tests below. CPPFLAGS="${protobuf_cxxflags} ${CPPFLAGS}" CXXFLAGS="${protobuf_cxxflags} ${CXXFLAGS}" ## look for protoc, the ProtoBuf compiler AC_DEFUN([AC_PROG_PROTOC], [AC_CHECK_PROG(PROTOC,protoc,yes)]) AC_PROG_PROTOC if test x"${PROTOC}" == x"no" ; then echo " Your installation does not appear to have protoc installed. Please make sure that you have a working and complete ProtoBuf installation. " exit 1 fi ## look for protobuf headers -- now use pkg-config which even does minimum version ## ## next two lines break witha autoconf 2.65 :-/ #PROTOBUF_VERSION="2.2.0" #PKG_CHECK_MODULES(ProtoBuf, protobuf >= 2.2.0, , AC_MSG_ERROR(Protobuf version 2.2.0 required)) ## check for header and ability to link ## first for headers Debian has in libprotobuf-dev protobuf_common_header=google/protobuf/stubs/common.h protobuf_common_header_cache_var=AS_TR_SH([ac_cv_header_$protobuf_common_header]) AC_CHECK_HEADER([$protobuf_common_header],, [ # If it didn't work, try adding /usr/local directly then trying again AC_MSG_WARN([Protobuf headers not found with default CXXFLAGS and CPPFLAGS, manually trying /usr/local/include]) CPPFLAGS="${protobuf_cxxflags} ${CPPFLAGS} -I/usr/local/include" CXXFLAGS="${protobuf_cxxflags} ${CXXFLAGS} -I/usr/local/include -L/usr/local/lib" # unset the cache variable for this particular header # check, so we can check again with different defaults # specified. AC_MSG_WARN([Unsetting $protobuf_common_header_cache_var]) AS_UNSET([$protobuf_common_header_cache_var]) AC_CHECK_HEADER([$protobuf_common_header],, [AC_MSG_ERROR([ERROR: ProtoBuf headers required; use '-Iincludedir' in CXXFLAGS for unusual locations.])]) ]) ## second for headers Debian has in libprotoc-dev AC_CHECK_HEADER(google/protobuf/compiler/code_generator.h,, [AC_MSG_ERROR([ERROR: ProtoBuf compiler headers required; use '-Iincludedir' in CXXFLAGS for unusual locations.])]) ## third check the lib itself #pb_savedlibs="$LIBS" # LIBS="$LIBS -lprotoc -lprotobuf -lpthread" LIBS="$LIBS $protobuf_libs" ## also check for minimum version AC_MSG_CHECKING([if ProtoBuf version >= 2.2.0]) AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include int main() { if (GOOGLE_PROTOBUF_VERSION >= 2001000) { exit (0); } else { exit(1); } } ]])], [pb_version_ok=yes], [pb_version_ok=no], [pb_version_ok=yes]) if test x"${pb_version_ok}" == x"no"; then AC_MSG_ERROR([Need ProtoBuf version >= 2.2.0]) else AC_MSG_RESULT([yes]) fi AC_DEFUN([AC_PROG_R], [AC_CHECK_PROG(R,R,yes)]) AC_PROG_R ## With thanks to Kurt : ${R_HOME=`R RHOME`} if test -z "${R_HOME}"; then AC_MSG_ERROR([Could not determine R_HOME.]) fi R_CXXFLAGS=`"${R_HOME}/bin/R" CMD config CXXFLAGS` CXXFLAGS="${CXXFLAGS} ${R_CXXFLAGS}" ## now use all these AC_SUBST([PKG_CPPFLAGS],["${PKG_CPPFLAGS} ${CXXFLAGS} ${protobuf_cxxflags}"]) AC_SUBST([PKG_LIBS],["${PKG_LIBS} ${protobuf_libs}"]) AC_CONFIG_FILES([src/Makevars]) AC_OUTPUT echo " RProtoBuf $PACKAGE_VERSION ================ cflags: ${PKG_CPPFLAGS} libs: ${PKG_LIBS} " RProtoBuf/tests/0000755000176200001440000000000013005133352013271 5ustar liggesusersRProtoBuf/tests/runUnitTests.R0000644000176200001440000000232713005133352016107 0ustar liggesusers ## doRUnit.R --- Run RUnit tests ## ## with credits to package fUtilities in RMetrics ## which credits Gregor Gojanc's example in CRAN package 'gdata' ## as per the R Wiki http://wiki.r-project.org/rwiki/doku.php?id=developers:runit ## and changed further by Martin Maechler ## and more changes by Murray Stokely in HistogramTools ## ## Dirk Eddelbuettel, Dec 2013 stopifnot(require("RUnit", quietly=TRUE)) stopifnot(require("RProtoBuf", quietly=TRUE)) # path <- system.file("unitTests", package = pkg) # stopifnot(file.exists(path), file.info(path.expand(path))$isdir) # source(file.path(path, "runTests.R"), echo = TRUE) ## Set a seed to make the test deterministic set.seed(42) ## Define tests testSuite <- defineTestSuite(name="RProtoBuf Unit Tests", dirs=system.file("unitTests", package = "RProtoBuf"), testFuncRegexp = "^[Tt]est.+") ## Run tests tests <- runTestSuite(testSuite) ## Print results printTextProtocol(tests) ## Return success or failure to R CMD CHECK if (getErrors(tests)$nFail > 0) { stop("TEST FAILED!") } if (getErrors(tests)$nErr > 0) { stop("TEST HAD ERRORS!") } if (getErrors(tests)$nTestFunc < 1) { stop("NO TEST FUNCTIONS RUN!") } RProtoBuf/src/0000755000176200001440000000000013164671424012733 5ustar liggesusersRProtoBuf/src/ZeroCopyOutputStreamWrapper.cpp0000644000176200001440000000137313164671424021153 0ustar liggesusers// -*- indent-tabs-mode: nil; tab-width: 4; show-trailing-whitespace: t; c-indent-level: 4; c-basic-offset: 4; -*- #include "rprotobuf.h" namespace rprotobuf { ZeroCopyOutputStreamWrapper::ZeroCopyOutputStreamWrapper(GPB::io::ZeroCopyOutputStream* stream) : stream(stream) { coded_stream = new GPB::io::CodedOutputStream(stream); } ZeroCopyOutputStreamWrapper::~ZeroCopyOutputStreamWrapper() { try { /* first clear the coded stream */ delete coded_stream; /* then the stream itself */ delete stream; } catch (...) { } } GPB::io::ZeroCopyOutputStream* ZeroCopyOutputStreamWrapper::get_stream() { return stream; } GPB::io::CodedOutputStream* ZeroCopyOutputStreamWrapper::get_coded_stream() { return coded_stream; } } // namespace rprotobuf RProtoBuf/src/wrapper_ServiceDescriptor.cpp0000644000176200001440000000635513164671424020647 0ustar liggesusers// -*- indent-tabs-mode: nil; tab-width: 4; show-trailing-whitespace: t; c-indent-level: 4; c-basic-offset: 4; -*- #include "rprotobuf.h" #include "RcppMacros.h" namespace rprotobuf { #undef METHOD #define METHOD(__NAME__) RCPP_PP_CAT(ServiceDescriptor__, __NAME__) RPB_XP_METHOD_0(METHOD(length), GPB::ServiceDescriptor, method_count) RPB_XP_METHOD_0(METHOD(method_count), GPB::ServiceDescriptor, method_count) RPB_XP_METHOD_0(METHOD(as_character), GPB::ServiceDescriptor, DebugString) RPB_XP_METHOD_CAST_1(METHOD(getMethodByIndex), GPB::ServiceDescriptor, method, S4_MethodDescriptor) RPB_XP_METHOD_CAST_1(METHOD(getMethodByName), GPB::ServiceDescriptor, FindMethodByName, S4_MethodDescriptor) RPB_FUNCTION_1(Rcpp::CharacterVector, METHOD(getMethodNames), Rcpp::XPtr desc) { int nmeths = desc->method_count(); Rcpp::CharacterVector res(nmeths); for (int i = 0; i < nmeths; i++) { res[i] = desc->method(i)->name(); } return res; } /** * @param xp (GPB::ServiceDescriptor*) external pointer * @return the descriptor as an R list */ RPB_FUNCTION_1(Rcpp::List, METHOD(as_list), Rcpp::XPtr desc) { int n = desc->method_count(); Rcpp::CharacterVector names(n); Rcpp::List res(n); for (int i = 0; i < n; i++) { const GPB::MethodDescriptor* met = desc->method(i); res[i] = S4_MethodDescriptor(met); names[i] = met->name(); } res.names() = names; return res; } RPB_FUNCTION_1(S4_Message, METHOD(as_Message), Rcpp::XPtr d) { GPB::ServiceDescriptorProto* message = new GPB::ServiceDescriptorProto(); d->CopyTo(message); return S4_Message(message); } RPB_FUNCTION_1(S4_FileDescriptor, METHOD(fileDescriptor), Rcpp::XPtr desc) { return S4_FileDescriptor(desc->file()); } RPB_FUNCTION_2(std::string, METHOD(name), Rcpp::XPtr d, bool full) { return full ? d->full_name() : d->name(); } /** * extract a method descriptor from a service descriptor using its * name or position * * @param pointer (GPB::ServiceDescriptor*) external pointer * @param name name or position of the method */ SEXP get_service_method(SEXP pointer, SEXP name) { /* grab the Message pointer */ Rcpp::XPtr desc(pointer); GPB::MethodDescriptor* method_desc = static_cast(0); switch (TYPEOF(name)) { case STRSXP: { /* what we are looking for */ const char* what = CHAR(STRING_ELT(name, 0)); /* the method descriptor */ method_desc = (GPB::MethodDescriptor*)desc->FindMethodByName(what); break; } case REALSXP: { /* the method descriptor */ method_desc = (GPB::MethodDescriptor*)desc->method((int)REAL(name)[0]); break; } case INTSXP: { /* the method descriptor */ method_desc = (GPB::MethodDescriptor*)desc->method(INTEGER(name)[0]); break; } } if (!method_desc) { Rcpp::stop("could not get MethodDescriptor"); } return S4_MethodDescriptor(method_desc); } #undef METHOD } // namespace rprotobuf RProtoBuf/src/wrapper_Descriptor.cpp0000644000176200001440000002131113164671424017313 0ustar liggesusers// -*- indent-tabs-mode: nil; tab-width: 4; show-trailing-whitespace: t; c-indent-level: 4; c-basic-offset: 4; -*- #include "rprotobuf.h" #include "RcppMacros.h" namespace rprotobuf { #undef METHOD #define METHOD(__NAME__) RCPP_PP_CAT(Descriptor__, __NAME__) RPB_XP_METHOD_0(METHOD(as_character), GPB::Descriptor, DebugString) RPB_XP_METHOD_0(METHOD(field_count), GPB::Descriptor, field_count) RPB_XP_METHOD_0(METHOD(nested_type_count), GPB::Descriptor, nested_type_count) RPB_XP_METHOD_0(METHOD(enum_type_count), GPB::Descriptor, enum_type_count) RPB_XP_METHOD_CAST_0(METHOD(containing_type), GPB::Descriptor, containing_type, S4_Descriptor) /** * returns the names of the members contained in the descriptor * (nested types, enums, fields) * * @param xp external pointer to a Descriptor * * @return member names, as an R character vector (STRSXP) */ RPB_FUNCTION_1(Rcpp::CharacterVector, METHOD(getMemberNames), Rcpp::XPtr desc) { int nfields = desc->field_count(); int ntypes = desc->nested_type_count(); int nenums = desc->enum_type_count(); Rcpp::CharacterVector res(nfields + ntypes + nenums); int j = 0; for (int i = 0; i < nfields; i++, j++) { res[j] = desc->field(i)->name(); } for (int i = 0; i < ntypes; i++, j++) { res[j] = desc->nested_type(i)->name(); } for (int i = 0; i < nenums; i++, j++) { res[j] = desc->enum_type(i)->name(); } return (res); } /** * @param xp external pointer to a Descriptor * @return the descriptor as an R list */ RPB_FUNCTION_1(Rcpp::List, METHOD(as_list), Rcpp::XPtr desc) { int nfields = desc->field_count(); int ntypes = desc->nested_type_count(); int nenums = desc->enum_type_count(); int n = nfields + ntypes + nenums; Rcpp::CharacterVector names(n); Rcpp::List res(n); int cnt = 0; for (int i = 0; i < nfields; cnt++, i++) { const GPB::FieldDescriptor* fd = desc->field(i); res[cnt] = S4_FieldDescriptor(fd); names[cnt] = fd->name(); } for (int i = 0; i < ntypes; cnt++, i++) { const GPB::Descriptor* d = desc->nested_type(i); res[cnt] = S4_Descriptor(d); names[cnt] = d->name(); } for (int i = 0; i < nenums; cnt++, i++) { const GPB::EnumDescriptor* ed = desc->enum_type(i); res[cnt] = S4_EnumDescriptor(ed); names[cnt] = ed->name(); } res.names() = names; return res; } RPB_FUNCTION_1(S4_Message, METHOD(as_Message), Rcpp::XPtr d) { GPB::DescriptorProto* message = new GPB::DescriptorProto(); d->CopyTo(message); return message; } RPB_FUNCTION_2(S4_FieldDescriptor, METHOD(field), Rcpp::XPtr d, int i) { return d->field(i); } RPB_FUNCTION_2(S4_FieldDescriptor, METHOD(FindFieldByNumber), Rcpp::XPtr d, int num) { return d->FindFieldByNumber(num); } RPB_FUNCTION_2(S4_FieldDescriptor, METHOD(FindFieldByName), Rcpp::XPtr d, std::string nam) { return d->FindFieldByName(nam); } RPB_FUNCTION_2(S4_Descriptor, METHOD(nested_type), Rcpp::XPtr d, int i) { return d->nested_type(i); } RPB_FUNCTION_2(S4_Descriptor, METHOD(FindNestedTypeByName), Rcpp::XPtr d, std::string nam) { return d->FindNestedTypeByName(nam); } RPB_FUNCTION_2(S4_EnumDescriptor, METHOD(enum_type), Rcpp::XPtr d, int i) { return d->enum_type(i); } // FIXME: two methods cant have the same name // RPB_FUNCTION_2( S4_EnumDescriptor, METHOD(enum_type), // Rcpp::XPtr d, std::string name){ // return d->FindEnumTypeByName( i ) ; // } RPB_FUNCTION_1(S4_FileDescriptor, METHOD(fileDescriptor), Rcpp::XPtr desc) { return S4_FileDescriptor(desc->file()); } RPB_FUNCTION_2(std::string, METHOD(name), Rcpp::XPtr d, bool full) { return full ? d->full_name() : d->name(); } RPB_FUNCTION_2(S4_Message, METHOD(readMessageFromFile), Rcpp::XPtr desc, std::string filename) { /* open the file to read in binary mode */ int file = open(filename.c_str(), O_RDONLY | O_BINARY); /* create a prototype of the message we are going to read */ GPB::Message* message = PROTOTYPE(desc); if (!message) { throw std::range_error("could not call factory->GetPrototype(desc)->New()"); } /* read the message from the file */ // TODO(mstokely): Check return value! message->ParsePartialFromFileDescriptor(file); close(file); return (S4_Message(message)); } RPB_FUNCTION_2(S4_Message, METHOD(readMessageFromConnection), Rcpp::XPtr desc, int conn_id) { RconnectionCopyingInputStream wrapper(conn_id); GPB::io::CopyingInputStreamAdaptor stream(&wrapper); GPB::io::CodedInputStream coded_stream(&stream); /* create a prototype of the message we are going to read */ GPB::Message* message = PROTOTYPE(desc); if (!message) { throw std::range_error("could not call factory->GetPrototype(desc)->New()"); } // TODO(mstokely): Check return value! message->ParsePartialFromCodedStream(&coded_stream); S4_Message res(message); return res; } RPB_FUNCTION_2(S4_Message, METHOD(readMessageFromRawVector), Rcpp::XPtr desc, Rcpp::RawVector raw) { GPB::io::ArrayInputStream ais((void*)raw.begin(), raw.size()); GPB::io::CodedInputStream stream(&ais); GPB::Message* message = PROTOTYPE(desc); if (!message) { throw std::range_error("could not call factory->GetPrototype(desc)->New()"); } message->MergePartialFromCodedStream(&stream); return (S4_Message(message)); } RPB_FUNCTION_3(S4_Message, METHOD(readASCIIFromString), Rcpp::XPtr desc, std::string input, bool partial) { GPB::Message* message = PROTOTYPE(desc); if (partial) { // Allow partial messages where object is not fully initialized GPB::TextFormat::Parser parser; parser.AllowPartialMessage(partial); if (parser.ParseFromString(input, message)) { return (S4_Message(message)); } else { throw std::range_error("Could not parse ASCII protocol buffer from text string."); } } else { // Default parser requires fully initialized ascii messages. if (GPB::TextFormat::ParseFromString(input, message)) { return (S4_Message(message)); } else { throw std::range_error("Could not parse ASCII protocol buffer from text string." " Consider setting partial=TRUE"); } } } RPB_FUNCTION_3(S4_Message, METHOD(readASCIIFromConnection), Rcpp::XPtr desc, int conn_id, bool partial) { RconnectionCopyingInputStream wrapper(conn_id); GPB::io::CopyingInputStreamAdaptor stream(&wrapper); /* create a prototype of the message we are going to read */ GPB::Message* message = PROTOTYPE(desc); if (!message) { throw std::range_error("could not call factory->GetPrototype(desc)->New()"); } if (partial) { // Allow partial messages where object is not fully initialized GPB::TextFormat::Parser parser; parser.AllowPartialMessage(partial); if (!parser.Parse(&stream, message)) { throw std::range_error("Could not parse ASCII protocol buffer."); } } else { // Default parser requires fully initialized ascii messages. if (!GPB::TextFormat::Parse(&stream, message)) { throw std::range_error("Could not parse ASCII protocol buffer."); } } if (wrapper.Failure()) { throw std::range_error("Could not read ASCII protocol buffer."); } return (S4_Message(message)); } RcppExport SEXP Descriptor_getField(SEXP pointer, SEXP name) { GPB::FieldDescriptor* field_desc = (GPB::FieldDescriptor*)0; BEGIN_RCPP std::string error_message = "could not get FieldDescriptor for field"; SEXP retVal = R_NilValue; switch (TYPEOF(name)) { case CHARSXP: case STRSXP: // This tries to get the field by name for various types of descriptors. retVal = do_dollar_Descriptor(pointer, name); if (retVal == R_NilValue) { error_message = "Unknown field"; } else { return retVal; } break; default: { error_message = "Invalid type for get field extractor."; break; } } if (!field_desc) { Rcpp::stop(error_message.c_str()); } return S4_FieldDescriptor(field_desc); VOID_END_RCPP return S4_FieldDescriptor(field_desc); } #undef METHOD } // namespace rprotobuf RProtoBuf/src/streams.cpp0000644000176200001440000002157313164671424015125 0ustar liggesusers// -*- indent-tabs-mode: nil; tab-width: 4; show-trailing-whitespace: t; c-indent-level: 4; c-basic-offset: 4; -*- #include "rprotobuf.h" #include "ConnectionInputStream.h" #include "ConnectionOutputStream.h" namespace rprotobuf { void ZeroCopyInputStreamWrapper_finalizer(SEXP xp) { delete (ZeroCopyInputStreamWrapper*)XPP(xp); } void ZeroCopyOutputStreamWrapper_finalizer(SEXP xp) { delete (ZeroCopyOutputStreamWrapper*)XPP(xp); } // {{{ input streams // {{{ FileInputStream SEXP FileInputStream_new(SEXP filename, SEXP block_size, SEXP close_on_delete) { BEGIN_RCPP NEW_S4_OBJECT("FileInputStream"); int fd = open(CHAR(STRING_ELT(filename, 0)), O_RDONLY | O_BINARY); GPB::io::FileInputStream* stream = new GPB::io::FileInputStream(fd, INTEGER(block_size)[0]); stream->SetCloseOnDelete(LOGICAL(close_on_delete)[0]); ZeroCopyInputStreamWrapper* wrapper = new ZeroCopyInputStreamWrapper(stream); SEXP ptr = PROTECT(R_MakeExternalPtr((void*)wrapper, R_NilValue, R_NilValue)); R_RegisterCFinalizerEx(ptr, ZeroCopyInputStreamWrapper_finalizer, _FALSE_); SET_SLOT(oo, Rf_install("pointer"), ptr); UNPROTECT(2); /* oo, ptr */ return oo; END_RCPP } SEXP FileInputStream_GetErrno(SEXP xp) { BEGIN_RCPP GPB::io::FileInputStream* stream = GET_FIS(xp); return Rf_ScalarInteger(stream->GetErrno()); END_RCPP } SEXP FileInputStream_SetCloseOnDelete(SEXP xp, SEXP close) { BEGIN_RCPP GPB::io::FileInputStream* stream = GET_FIS(xp); stream->SetCloseOnDelete(LOGICAL(close)); return R_NilValue; END_RCPP } SEXP FileInputStream_Close(SEXP xp) { BEGIN_RCPP GPB::io::FileInputStream* stream = GET_FIS(xp); bool res = stream->Close(); return Rf_ScalarLogical(res ? _TRUE_ : _FALSE_); END_RCPP } // }}} // {{{ ConnectionInputStream SEXP ConnectionInputStream_new(SEXP con, SEXP was_open) { BEGIN_RCPP NEW_S4_OBJECT("ConnectionInputStream"); ConnectionInputStream* stream = new ConnectionInputStream(con, (bool)LOGICAL(was_open)[0]); ZeroCopyInputStreamWrapper* wrapper = new ZeroCopyInputStreamWrapper(stream); SEXP ptr = PROTECT(R_MakeExternalPtr((void*)wrapper, R_NilValue, con)); R_RegisterCFinalizerEx(ptr, ZeroCopyInputStreamWrapper_finalizer, _FALSE_); SET_SLOT(oo, Rf_install("pointer"), ptr); UNPROTECT(2); /* oo, ptr */ return oo; END_RCPP } // }}} // }}} // {{{ output streams // {{{ ZeroCopyOutputStream SEXP ZeroCopyOutputStream_Next(SEXP xp, SEXP payload) { BEGIN_RCPP GPB::io::ZeroCopyOutputStream* stream = GET_ZCOS(xp); void* out; int s = LENGTH(payload); bool res = stream->Next(&out, &s); if (!res) { Rcpp_error("cannot write to stream"); } memcpy(out, RAW(payload), s); return Rf_ScalarInteger(s); END_RCPP } SEXP ZeroCopyOutputStream_ByteCount(SEXP xp) { BEGIN_RCPP GPB::io::ZeroCopyOutputStream* stream = GET_ZCOS(xp); return (Rf_ScalarReal((double)stream->ByteCount())); END_RCPP } SEXP ZeroCopyOutputStream_BackUp(SEXP xp, SEXP count) { BEGIN_RCPP GPB::io::ZeroCopyOutputStream* stream = GET_ZCOS(xp); int s = GET_int(count, 0); stream->BackUp(s); return R_NilValue; END_RCPP } // }}} // {{{ ArrayOutputStream // }}} // {{{ FileOutputStream SEXP FileOutputStream_new(SEXP filename, SEXP block_size, SEXP close_on_delete) { BEGIN_RCPP NEW_S4_OBJECT("FileOutputStream"); int fd = open(CHAR(STRING_ELT(filename, 0)), O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666); GPB::io::FileOutputStream* stream = new GPB::io::FileOutputStream(fd, INTEGER(block_size)[0]); stream->SetCloseOnDelete(LOGICAL(close_on_delete)[0]); ZeroCopyOutputStreamWrapper* wrapper = new ZeroCopyOutputStreamWrapper(stream); SEXP ptr = PROTECT(R_MakeExternalPtr((void*)wrapper, R_NilValue, R_NilValue)); R_RegisterCFinalizerEx(ptr, ZeroCopyOutputStreamWrapper_finalizer, _FALSE_); SET_SLOT(oo, Rf_install("pointer"), ptr); UNPROTECT(2); /* oo, ptr */ return oo; END_RCPP } SEXP FileOutputStream_Flush(SEXP xp) { BEGIN_RCPP GPB::io::FileOutputStream* stream = GET_FOS(xp); bool res = stream->Flush(); return Rf_ScalarLogical(res ? _TRUE_ : _FALSE_); END_RCPP } SEXP FileOutputStream_Close(SEXP xp) { BEGIN_RCPP GPB::io::FileOutputStream* stream = GET_FOS(xp); bool res = stream->Close(); return Rf_ScalarLogical(res ? _TRUE_ : _FALSE_); END_RCPP } SEXP FileOutputStream_GetErrno(SEXP xp) { BEGIN_RCPP GPB::io::FileOutputStream* stream = GET_FOS(xp); return Rf_ScalarInteger(stream->GetErrno()); END_RCPP } SEXP FileOutputStream_SetCloseOnDelete(SEXP xp, SEXP close) { BEGIN_RCPP GPB::io::FileOutputStream* stream = GET_FOS(xp); stream->SetCloseOnDelete(LOGICAL(close)); return R_NilValue; END_RCPP } // }}} // {{{ ConnectionOutputStream SEXP ConnectionOutputStream_new(SEXP con, SEXP was_open) { BEGIN_RCPP NEW_S4_OBJECT("ConnectionOutputStream"); ConnectionOutputStream* stream = new ConnectionOutputStream(con, (bool)LOGICAL(was_open)[0]); ZeroCopyOutputStreamWrapper* wrapper = new ZeroCopyOutputStreamWrapper(stream); /* we keep the R connection protected as long as the external pointer is kept out of GC */ SEXP ptr = PROTECT(R_MakeExternalPtr((void*)wrapper, R_NilValue, con)); R_RegisterCFinalizerEx(ptr, ZeroCopyOutputStreamWrapper_finalizer, _FALSE_); SET_SLOT(oo, Rf_install("pointer"), ptr); UNPROTECT(2); /* oo, ptr */ return oo; END_RCPP } // }}} // }}} // {{{ Read*** functions using CodedInputStream SEXP ZeroCopyInputStream_ReadRaw(SEXP xp, SEXP size) { BEGIN_RCPP GPB::io::CodedInputStream* coded_stream = GET_CIS(xp); int s = INTEGER(size)[0]; SEXP payload = PROTECT(Rf_allocVector(RAWSXP, s)); if (!coded_stream->ReadRaw(RAW(payload), s)) Rcpp_error("error reading raw bytes"); UNPROTECT(1); /* payload */ return payload; END_RCPP } SEXP ZeroCopyInputStream_ReadString(SEXP xp, SEXP size) { BEGIN_RCPP GPB::io::CodedInputStream* coded_stream = GET_CIS(xp); int s = INTEGER(size)[0]; std::string buffer(""); if (!coded_stream->ReadString(&buffer, s)) Rcpp_error("error reading string"); return Rf_mkString(buffer.c_str()); END_RCPP } SEXP ZeroCopyInputStream_ReadVarint32(SEXP xp) { BEGIN_RCPP GPB::io::CodedInputStream* coded_stream = GET_CIS(xp); uint32 res = 0; if (!coded_stream->ReadVarint32(&res)) Rcpp_error("error reading varint32"); return Rf_ScalarInteger(res); END_RCPP } SEXP ZeroCopyInputStream_ReadLittleEndian32(SEXP xp) { BEGIN_RCPP GPB::io::CodedInputStream* coded_stream = GET_CIS(xp); uint32 res = 0; if (!coded_stream->ReadVarint32(&res)) Rcpp_error("error reading little endian int32"); return Rf_ScalarInteger(res); END_RCPP } SEXP ZeroCopyInputStream_ReadLittleEndian64(SEXP xp) { BEGIN_RCPP GPB::io::CodedInputStream* coded_stream = GET_CIS(xp); uint64 res = 0; if (!coded_stream->ReadVarint64(&res)) Rcpp_error("error reading little endian int32"); return Rf_ScalarReal((double)res); END_RCPP } SEXP ZeroCopyInputStream_ReadVarint64(SEXP xp) { BEGIN_RCPP GPB::io::CodedInputStream* coded_stream = GET_CIS(xp); uint64 res = 0; if (!coded_stream->ReadVarint64(&res)) Rcpp_error("error reading varint64"); return Rf_ScalarReal((double)res); END_RCPP } // }}} // {{{ Write*** functions using CodedOuputStream SEXP ZeroCopyOutputStream_WriteRaw(SEXP xp, SEXP payload) { BEGIN_RCPP GPB::io::CodedOutputStream* stream = GET_COS(xp); stream->WriteRaw(RAW(payload), LENGTH(payload)); return R_NilValue; END_RCPP } SEXP ZeroCopyOutputStream_WriteString(SEXP xp, SEXP payload) { BEGIN_RCPP if (LENGTH(payload) > 1) { Rf_warning("only the first element is used"); } if (LENGTH(payload) == 0) { Rcpp_error("need at least one element"); } GPB::io::CodedOutputStream* stream = GET_COS(xp); stream->WriteString(CHAR(STRING_ELT(payload, 0))); return R_NilValue; END_RCPP } SEXP ZeroCopyOutputStream_WriteLittleEndian32(SEXP xp, SEXP payload) { BEGIN_RCPP GPB::io::CodedOutputStream* stream = GET_COS(xp); stream->WriteLittleEndian32(GET_int32(payload, 0)); return R_NilValue; END_RCPP } SEXP ZeroCopyOutputStream_WriteLittleEndian64(SEXP xp, SEXP payload) { BEGIN_RCPP GPB::io::CodedOutputStream* stream = GET_COS(xp); stream->WriteLittleEndian64(GET_int64(payload, 0)); return R_NilValue; END_RCPP } SEXP ZeroCopyOutputStream_WriteVarint32(SEXP xp, SEXP payload) { BEGIN_RCPP GPB::io::CodedOutputStream* stream = GET_COS(xp); stream->WriteVarint32(GET_int32(payload, 0)); return R_NilValue; END_RCPP } SEXP ZeroCopyOutputStream_WriteVarint64(SEXP xp, SEXP payload) { BEGIN_RCPP GPB::io::CodedOutputStream* stream = GET_COS(xp); stream->WriteVarint64(GET_int64(payload, 0)); return R_NilValue; END_RCPP } // }}} } // namespace rprotobuf RProtoBuf/src/ConnectionCopyingOutputStream.cpp0000644000176200001440000000107113164671424021463 0ustar liggesusers// -*- indent-tabs-mode: nil; tab-width: 4; show-trailing-whitespace: t; c-indent-level: 4; c-basic-offset: 4; -*- #include "rprotobuf.h" #include "ConnectionCopyingOutputStream.h" namespace rprotobuf { ConnectionCopyingOutputStream::ConnectionCopyingOutputStream(SEXP con) : con(con), writeBin("writeBin") {} bool ConnectionCopyingOutputStream::Write(const void* buffer, int size) { /* we need to take care of error handling */ Rcpp::RawVector payload(size); memcpy(payload.begin(), buffer, size); writeBin(payload, con); return true; } } RProtoBuf/src/wrapper_FieldDescriptor.cpp0000644000176200001440000000724713164671424020273 0ustar liggesusers// -*- indent-tabs-mode: nil; tab-width: 4; show-trailing-whitespace: t; c-indent-level: 4; c-basic-offset: 4; -*- // Copyright (C) 2010 - 2011 Dirk Eddelbuettel and Romain Francois // // This file is part of RProtoBuf. // // RProtoBuf is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // RProtoBuf is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with RProtoBuf. If not, see . #include "rprotobuf.h" #include "fieldtypes.h" #include "RcppMacros.h" namespace rprotobuf { #undef METHOD #define METHOD(__NAME__) RCPP_PP_CAT(FieldDescriptor__, __NAME__) RPB_XP_METHOD_0(METHOD(as_character), GPB::FieldDescriptor, DebugString) RPB_XP_METHOD_0(METHOD(is_extension), GPB::FieldDescriptor, is_extension) RPB_XP_METHOD_0(METHOD(number), GPB::FieldDescriptor, number) RPB_XP_METHOD_0(METHOD(type), GPB::FieldDescriptor, type) RPB_XP_METHOD_0(METHOD(cpp_type), GPB::FieldDescriptor, cpp_type) RPB_XP_METHOD_0(METHOD(label), GPB::FieldDescriptor, label) RPB_XP_METHOD_0(METHOD(is_repeated), GPB::FieldDescriptor, is_repeated) RPB_XP_METHOD_0(METHOD(is_optional), GPB::FieldDescriptor, is_optional) RPB_XP_METHOD_0(METHOD(is_required), GPB::FieldDescriptor, is_required) RPB_XP_METHOD_0(METHOD(has_default_value), GPB::FieldDescriptor, has_default_value) RPB_FUNCTION_1(S4_Descriptor, METHOD(containing_type), Rcpp::XPtr d) { return S4_Descriptor(d->containing_type()); } #define RPB_HANDLE_CASE(__CPP__, __LC__) \ case CPPTYPE_##__CPP__: { \ return Rcpp::wrap(d->default_value_##__LC__()); \ } RPB_FUNCTION_1(SEXP, METHOD(default_value), Rcpp::XPtr d) { switch (d->cpp_type()) { RPB_HANDLE_CASE(INT32, int32) RPB_HANDLE_CASE(UINT32, uint32) #ifdef RCPP_HAS_LONG_LONG_TYPES RPB_HANDLE_CASE(INT64, int64) RPB_HANDLE_CASE(UINT64, uint64) #endif RPB_HANDLE_CASE(DOUBLE, double) RPB_HANDLE_CASE(FLOAT, float) RPB_HANDLE_CASE(BOOL, bool) RPB_HANDLE_CASE(STRING, string) case CPPTYPE_ENUM: { return Rf_ScalarInteger(d->default_value_enum()->number()); } default: break; } return R_NilValue; } RPB_FUNCTION_1(S4_Descriptor, METHOD(message_type), Rcpp::XPtr d) { if (d->cpp_type() != CPPTYPE_MESSAGE) { throw Rcpp::not_compatible("not a message type field"); } return S4_Descriptor(d->message_type()); } RPB_FUNCTION_1(S4_EnumDescriptor, METHOD(enum_type), Rcpp::XPtr d) { if (d->cpp_type() != CPPTYPE_ENUM) { Rcpp::stop("not an enum type field"); } return S4_EnumDescriptor(d->enum_type()); } RPB_FUNCTION_1(S4_Message, METHOD(as_Message), Rcpp::XPtr d) { GPB::FieldDescriptorProto* message = new GPB::FieldDescriptorProto(); d->CopyTo(message); return S4_Message(message); } RPB_FUNCTION_1(S4_FileDescriptor, METHOD(fileDescriptor), Rcpp::XPtr desc) { return S4_FileDescriptor(desc->file()); } RPB_FUNCTION_2(std::string, METHOD(name), Rcpp::XPtr d, bool full) { return full ? d->full_name() : d->name(); } #undef RPB_HANDLE_CASE #undef METHOD } // namespace rprotobuf RProtoBuf/src/ConnectionCopyingInputStream.cpp0000644000176200001440000000134713164671424021270 0ustar liggesusers// -*- indent-tabs-mode: nil; tab-width: 4; show-trailing-whitespace: t; c-indent-level: 4; c-basic-offset: 4; -*- #include "rprotobuf.h" #include "ConnectionCopyingInputStream.h" namespace rprotobuf { ConnectionCopyingInputStream::ConnectionCopyingInputStream(SEXP con) : con(con), readBin("readBin") {} /** * call readBin to read size bytes from R * * @param buffer buffer to fill with at most size bytes * @param size maximum number of bytes * * @return the number of bytes actually read */ int ConnectionCopyingInputStream::Read(void* buffer, int size) { /* TODO: error handling */ Rcpp::RawVector res = readBin(con, Rcpp::RawVector(0), size); memcpy(buffer, res.begin(), res.size()); return res.size(); } } RProtoBuf/src/DescriptorPoolLookup.cpp0000644000176200001440000000677713164671424017622 0ustar liggesusers// -*- indent-tabs-mode: nil; tab-width: 4; show-trailing-whitespace: t; c-indent-level: 4; c-basic-offset: 4; -*- // DescriptorPoolLookup.cpp: R/C++ interface class library // // Copyright (C) 2010 - 2011 Dirk Eddelbuettel and Romain Francois // // This file is part of RProtoBuf. // // RProtoBuf is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // RProtoBuf is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with RProtoBuf. If not, see . #include "rprotobuf.h" #include "DescriptorPoolLookup.h" namespace rprotobuf { void DescriptorPoolLookup::add(const std::string& element) { elements.insert(element); } bool DescriptorPoolLookup::contains(const std::string& element) { return elements.find(element) != elements.end(); } SEXP DescriptorPoolLookup::getElements() { return Rcpp::wrap(elements); } std::set DescriptorPoolLookup::elements; RWarningErrorCollector DescriptorPoolLookup::error_collector; RSourceTree DescriptorPoolLookup::source_tree; GPB::compiler::Importer DescriptorPoolLookup::importer(&source_tree, &error_collector); GPB::DynamicMessageFactory DescriptorPoolLookup::message_factory(importer.pool()); /** * Add descriptors from a proto file to the descriptor pool. * * Specifically, message types, extensions, and enums are added. * Services are not added because they are not really used in RProtoBuf. * * @param files A character vector of .proto files to import. * @param dirs A character vector of directories to import from. * @throws Rcpp::exception if a file can't be loaded (uncaught). */ void DescriptorPoolLookup::importProtoFiles(SEXP files, SEXP dirs) { source_tree.addDirectories(dirs); int n = LENGTH(files); for (int j = 0; j < n; j++) { const GPB::FileDescriptor* file_desc = importer.Import(CHAR(STRING_ELT(files, j))); if (!file_desc) { std::string message = std::string("Could not load proto file '") + CHAR(STRING_ELT(files, j)) + "'\n"; Rcpp_error(message.c_str()); } // add top level messages from the file. int ntypes = file_desc->message_type_count(); for (int i = 0; i < ntypes; i++) { const GPB::Descriptor* desc = file_desc->message_type(i); add(desc->full_name()); /* should we bother recursing ? */ } // add top level extensions int nexts = file_desc->extension_count(); for (int i = 0; i < nexts; i++) { const GPB::FieldDescriptor* field_desc = file_desc->extension(i); add(field_desc->full_name()); } // add top level enums. int nenums = file_desc->enum_type_count(); for (int i = 0; i < nenums; i++) { const GPB::EnumDescriptor* enum_desc = file_desc->enum_type(i); add(enum_desc->full_name()); } } // source_tree.removeDirectories( dirs ) ; } const GPB::DescriptorPool* DescriptorPoolLookup::pool() { return importer.pool(); } const GPB::DynamicMessageFactory* DescriptorPoolLookup::factory() { return &message_factory; } } // namespace rprotobuf RProtoBuf/src/DescriptorPoolLookup.h0000644000176200001440000000156213164671424017252 0ustar liggesusers#ifndef RPROTOBUF_DescriptorPoolLookup_H #define RPROTOBUF_DescriptorPoolLookup_H #include /* For set */ #include /* For string */ #include "RSourceTree.h" #include "RWarningErrorCollector.h" namespace rprotobuf { class DescriptorPoolLookup { public: static void add(const std::string& element); static bool contains(const std::string& element); static SEXP getElements(); static void importProtoFiles(SEXP files, SEXP cwd); static const GPB::DescriptorPool* pool(); static const GPB::DynamicMessageFactory* factory(); private: static std::set elements; static RWarningErrorCollector error_collector; static RSourceTree source_tree; static GPB::compiler::Importer importer; static GPB::DynamicMessageFactory message_factory; }; } // namespace rprotobuf #endif RProtoBuf/src/lookup.cpp0000644000176200001440000001654713164671424014765 0ustar liggesusers// -*- indent-tabs-mode: nil; tab-width: 4; show-trailing-whitespace: t; c-indent-level: 4; c-basic-offset: 4; -*- #include "rprotobuf.h" #include "DescriptorPoolLookup.h" /* This uses the mechanism of the RObjectTables package see: http://www.omegahat.net/RObjectTables/ */ namespace rprotobuf { /** * Returns the R_UnboundValue */ SEXP R_getUnboundValue() { return (R_UnboundValue); } /** * @param name potential message type * @param canCache Can R cache this object * @param tb object table * * @return _TRUE_ if there is a message of the given type in the DescriptorPool */ Rboolean rProtoBufTable_exists(const char *const name, Rboolean *canCache, R_ObjectTable *tb) { #ifdef LOOKUP_DEBUG Rprintf(" >> rProtoBufTable_exists\n"); #endif if (tb->active == _FALSE_) return (_FALSE_); tb->active = _FALSE_; Rboolean val = _FALSE_; if (DescriptorPoolLookup::contains(name)) { /* first check the cache */ val = _TRUE_; } else { /* try the generated pool */ const GPB::DescriptorPool *pool = GPB::DescriptorPool::generated_pool(); if (pool->FindMessageTypeByName(name) || pool->FindEnumTypeByName(name) || pool->FindServiceByName(name) || pool->FindMethodByName(name) || pool->FindExtensionByName(name)) { DescriptorPoolLookup::add(name); val = _TRUE_; } else { /* try the runtime pool */ pool = DescriptorPoolLookup::pool(); if (pool->FindMessageTypeByName(name) || pool->FindEnumTypeByName(name) || pool->FindServiceByName(name) || pool->FindMethodByName(name) || pool->FindExtensionByName(name)) { DescriptorPoolLookup::add(name); val = _TRUE_; } } } tb->active = _TRUE_; return (val); } SEXP findSomething(const GPB::DescriptorPool *pool, const char *const name) { const GPB::Descriptor *desc = pool->FindMessageTypeByName(name); std::string name_string(name); if (desc) { /* message */ DescriptorPoolLookup::add(name_string); return S4_Descriptor(desc); } else { const GPB::EnumDescriptor *enum_desc = pool->FindEnumTypeByName(name_string); if (enum_desc) { /* enum */ DescriptorPoolLookup::add(name_string); return S4_EnumDescriptor(enum_desc); } else { const GPB::FieldDescriptor *extension_desc = pool->FindExtensionByName(name_string); if (extension_desc) { /* extension */ DescriptorPoolLookup::add(name_string); return S4_FieldDescriptor(extension_desc); } else { const GPB::ServiceDescriptor *service_desc = pool->FindServiceByName(name_string); if (service_desc) { DescriptorPoolLookup::add(name_string); return S4_ServiceDescriptor(service_desc); } else { const GPB::MethodDescriptor *method_desc = pool->FindMethodByName(name_string); if (method_desc) { DescriptorPoolLookup::add(name_string); return S4_MethodDescriptor(method_desc); } } } } } return R_NilValue; } /** * Returns a new "Descriptor" if there is such a message type * in the descriptor pool. NULL otherwise * * @param name message type name (without package path) * @param canCache * @param tb lookup table */ SEXP rProtoBufTable_get(const char *const name, Rboolean *canCache, R_ObjectTable *tb) { #ifdef LOOKUP_DEBUG Rprintf(" >> rProtoBufTable_get\n"); #endif if (tb->active == _FALSE_) return (R_UnboundValue); tb->active = _FALSE_; SEXP res_generated; SEXP res_runtime; int np = 0; /* first try the generated pool */ const GPB::DescriptorPool *pool = GPB::DescriptorPool::generated_pool(); res_generated = PROTECT(findSomething(pool, name)); np++; if (res_generated == R_NilValue) { /* try the runtime pool */ pool = DescriptorPoolLookup::pool(); res_runtime = PROTECT(findSomething(pool, name)); np++; } tb->active = _TRUE_; SEXP res = PROTECT((np == 2) ? res_runtime : res_generated); UNPROTECT(np + 1); if (res != R_NilValue) return res; return R_getUnboundValue(); // -Wall } /** * Does nothing. Not applicable */ int rProtoBufTable_remove(const char *const unused_name, R_ObjectTable *unused_tb) { #ifdef LOOKUP_DEBUG Rprintf(" >> rProtoBufTable_remove( %s) \n", unused_name); #endif Rf_error("cannot remove from protobuf descriptor pool"); return (0); // make -Wall happy } /** * Indicates if R can cache the variable name. * Currently allways return _FALSE_ * * @param name message type name * @param tb lookup table * @return allways _FALSE_ (for now) */ Rboolean rProtoBufTable_canCache(const char *const unused_name, R_ObjectTable *unused_tb) { #ifdef LOOKUP_DEBUG Rprintf(" >> rProtoBufTable_canCache\n"); #endif return (_FALSE_); } /** * Previously this function returned a stop() error, but this has side * effects such as preventing users from using '<<-' operator in any * scripts that include RProtoBuf. So instead, we now simply return * NULL to indicate assign is not possible on this lookup table * without giving such a hard error. */ SEXP rProtoBufTable_assign(const char *const unused_name, SEXP unused_value, R_ObjectTable *unused_tb) { #ifdef LOOKUP_DEBUG Rprintf(" >> rProtoBufTable_assign( %s ) \n", unused_name); #endif return (R_NilValue); // make -Wall happy } /** * Returns the list of classes known to be included in the * packages. * * @param tb lookup table */ SEXP rProtoBufTable_objects(R_ObjectTable *tb) { #ifdef LOOKUP_DEBUG Rprintf(" >> rProtoBufTable_objects\n"); #endif tb->active = _FALSE_; SEXP objects = PROTECT(DescriptorPoolLookup::getElements()); tb->active = _TRUE_; UNPROTECT(1); /* objects */ return (objects); } RcppExport SEXP newProtocolBufferLookup(SEXP possexp) { BEGIN_RCPP #ifdef LOOKUP_DEBUG Rprintf("\n"); #endif R_ObjectTable *tb; SEXP val, klass; tb = (R_ObjectTable *)malloc(sizeof(R_ObjectTable)); if (!tb) throw Rcpp::exception("cannot allocate space for an internal R object table"); tb->type = RPROTOBUF_LOOKUP; /* FIXME: not sure what this should be */ tb->cachedNames = NULL; tb->privateData = (void *)0; tb->exists = rProtoBufTable_exists; tb->get = rProtoBufTable_get; tb->remove = rProtoBufTable_remove; tb->assign = rProtoBufTable_assign; tb->objects = rProtoBufTable_objects; tb->canCache = rProtoBufTable_canCache; tb->onAttach = NULL; tb->onDetach = NULL; PROTECT(val = R_MakeExternalPtr(tb, Rf_install("UserDefinedDatabase"), R_NilValue)); PROTECT(klass = Rf_mkString("UserDefinedDatabase")); Rf_setAttrib(val, R_ClassSymbol, klass); UNPROTECT(2); /* val, klass */ #ifdef LOOKUP_DEBUG Rprintf("\n"); #endif Rcpp::Function fun("attach"); int pos = Rcpp::as(possexp); fun(val, Rcpp::Named("pos") = pos, Rcpp::Named("name") = "RProtoBuf:DescriptorPool"); // TODO(mstokely): Somewhere we should deallocate tb? If package is unattached? return (val); END_RCPP } } // namespace rprotobuf RProtoBuf/src/RconnectionCopyingInputStream.h0000644000176200001440000000065713164671424021122 0ustar liggesusers#ifndef RPROTOBUF_RconnectionCopyingInputStream_H #define RPROTOBUF_RconnectionCopyingInputStream_H namespace rprotobuf { class RconnectionCopyingInputStream : public GPB::io::CopyingInputStream { public: RconnectionCopyingInputStream(int id); int Read(void* buffer, int size); bool Failure() const { return (failure); } private: int connection_id; bool failure; }; } // namespace rprotobuf #endif RProtoBuf/src/RSourceTree.h0000644000176200001440000000100313164671424015300 0ustar liggesusers#ifndef RPROTOBUF_RSourceTree_H #define RPROTOBUF_RSourceTree_H namespace rprotobuf { class RSourceTree : public GPB::compiler::SourceTree { public: RSourceTree(); GPB::io::ZeroCopyInputStream* Open(const std::string& filename); void addDirectory(const std::string& directory); void addDirectories(SEXP dirs); void removeDirectory(const std::string& directory); void removeDirectories(SEXP dirs); private: std::set directories; }; } // namespace rprotobuf #endif RProtoBuf/src/wrapper_MethodDescriptor.cpp0000644000176200001440000000365313164671424020465 0ustar liggesusers// -*- indent-tabs-mode: nil; tab-width: 4; show-trailing-whitespace: t; c-indent-level: 4; c-basic-offset: 4; -*- #include "rprotobuf.h" #include "RcppMacros.h" namespace rprotobuf { #undef METHOD #define METHOD(__NAME__) RCPP_PP_CAT(MethodDescriptor__, __NAME__) RPB_XP_METHOD_0(METHOD(as_character), GPB::MethodDescriptor, DebugString) RPB_FUNCTION_1(S4_Message, METHOD(as_Message), Rcpp::XPtr d) { GPB::MethodDescriptorProto* message = new GPB::MethodDescriptorProto(); d->CopyTo(message); return S4_Message(message); } RPB_FUNCTION_1(S4_FileDescriptor, METHOD(fileDescriptor), Rcpp::XPtr desc) { return S4_FileDescriptor(desc->service()->file()); } RPB_FUNCTION_1(S4_Descriptor, METHOD(input_type), Rcpp::XPtr method) { return method->input_type(); } RPB_FUNCTION_1(S4_Descriptor, METHOD(output_type), Rcpp::XPtr method) { return method->output_type(); } RPB_FUNCTION_1(S4_Message, get_method_input_prototype, Rcpp::XPtr method) { const GPB::Descriptor* desc = method->input_type(); return S4_Message(PROTOTYPE(desc)); } RPB_FUNCTION_1(S4_Message, get_method_output_prototype, Rcpp::XPtr method) { const GPB::Descriptor* desc = method->output_type(); return S4_Message(PROTOTYPE(desc)); } RPB_FUNCTION_2(bool, valid_input_message, Rcpp::XPtr method, Rcpp::XPtr message) { return message->GetDescriptor() == method->input_type(); } RPB_FUNCTION_2(bool, valid_output_message, Rcpp::XPtr method, Rcpp::XPtr message) { return message->GetDescriptor() == method->output_type(); } RPB_FUNCTION_2(std::string, METHOD(name), Rcpp::XPtr d, bool full) { return full ? d->full_name() : d->name(); } #undef METHOD } // namespace rprotobuf RProtoBuf/src/wrapper_EnumValueDescriptor.cpp0000644000176200001440000000343213164671424021141 0ustar liggesusers// -*- indent-tabs-mode: nil; tab-width: 4; show-trailing-whitespace: t; c-indent-level: 4; c-basic-offset: 4; -*- // wrapper_EnumValueDescriptor.h: R/C++ interface class library // // Copyright (C) 2010 - 2011 Dirk Eddelbuettel and Romain Francois // // This file is part of RProtoBuf. // // RProtoBuf is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // RProtoBuf is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with RProtoBuf. If not, see . #include "rprotobuf.h" #include "RcppMacros.h" namespace rprotobuf { #undef METHOD #define METHOD(__NAME__) RCPP_PP_CAT(EnumValueDescriptor__, __NAME__) RPB_XP_METHOD_0(METHOD(as_character), GPB::EnumValueDescriptor, DebugString) RPB_FUNCTION_1(S4_Message, METHOD(as_Message), Rcpp::XPtr d) { GPB::EnumValueDescriptorProto* message = new GPB::EnumValueDescriptorProto(); d->CopyTo(message); return S4_Message(message); } RPB_FUNCTION_2(std::string, METHOD(name), Rcpp::XPtr d, bool full) { return full ? d->full_name() : d->name(); } RPB_FUNCTION_1(int, METHOD(number), Rcpp::XPtr d) { return d->number(); } RPB_FUNCTION_1(S4_EnumDescriptor, METHOD(enum_type), Rcpp::XPtr d) { return S4_EnumDescriptor(d->type()); } #undef METHOD } // namespace rprotobuf RProtoBuf/src/fieldtypes.h0000644000176200001440000000307513164671424015261 0ustar liggesusers#ifndef FIELD_TYPES_H #define FIELD_TYPES_H using namespace google::protobuf; #define TYPE_DOUBLE FieldDescriptor::TYPE_DOUBLE #define TYPE_FLOAT FieldDescriptor::TYPE_FLOAT #define TYPE_INT64 FieldDescriptor::TYPE_INT64 #define TYPE_UINT64 FieldDescriptor::TYPE_UINT64 #define TYPE_INT32 FieldDescriptor::TYPE_INT32 #define TYPE_FIXED64 FieldDescriptor::TYPE_FIXED64 #define TYPE_FIXED32 FieldDescriptor::TYPE_FIXED32 #define TYPE_BOOL FieldDescriptor::TYPE_BOOL #define TYPE_STRING FieldDescriptor::TYPE_STRING #define TYPE_GROUP FieldDescriptor::TYPE_GROUP #define TYPE_MESSAGE FieldDescriptor::TYPE_MESSAGE #define TYPE_BYTES FieldDescriptor::TYPE_BYTES #define TYPE_UINT32 FieldDescriptor::TYPE_UINT32 #define TYPE_ENUM FieldDescriptor::TYPE_ENUM #define TYPE_SFIXED32 FieldDescriptor::TYPE_SFIXED32 #define TYPE_SFIXED64 FieldDescriptor::TYPE_SFIXED64 #define TYPE_SINT32 FieldDescriptor::TYPE_SINT32 #define TYPE_SINT64 FieldDescriptor::TYPE_SINT64 #define MAX_TYPE FieldDescriptor::MAX_TYPE #define CPPTYPE_INT32 FieldDescriptor::CPPTYPE_INT32 #define CPPTYPE_INT64 FieldDescriptor::CPPTYPE_INT64 #define CPPTYPE_UINT32 FieldDescriptor::CPPTYPE_UINT32 #define CPPTYPE_UINT64 FieldDescriptor::CPPTYPE_UINT64 #define CPPTYPE_DOUBLE FieldDescriptor::CPPTYPE_DOUBLE #define CPPTYPE_FLOAT FieldDescriptor::CPPTYPE_FLOAT #define CPPTYPE_BOOL FieldDescriptor::CPPTYPE_BOOL #define CPPTYPE_ENUM FieldDescriptor::CPPTYPE_ENUM #define CPPTYPE_STRING FieldDescriptor::CPPTYPE_STRING #define CPPTYPE_MESSAGE FieldDescriptor::CPPTYPE_MESSAGE #define MAX_CPPTYPE FieldDescriptor::MAX_CPPTYPE #endif RProtoBuf/src/extractors.cpp0000644000176200001440000001665013164671424015645 0ustar liggesusers// -*- indent-tabs-mode: nil; tab-width: 4; show-trailing-whitespace: t; c-indent-level: 4; c-basic-offset: 4; -*- // Copyright (C) 2010 - 2011 Dirk Eddelbuettel and Romain Francois // // This file is part of RProtoBuf. // // RProtoBuf is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // RProtoBuf is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with RProtoBuf. If not, see . #include "rprotobuf.h" #include "fieldtypes.h" #include "Rcppsupport.h" namespace rprotobuf { const char* kIntStringOptionName = "RProtoBuf.int64AsString"; bool UseStringsForInt64() { static const SEXP option_name = Rf_install(kIntStringOptionName); return (Rf_asLogical(Rf_GetOption1(option_name))); } // Rcpp::wrap silently coerces 64-bit integers to numerics // which drop precision for values between 2^53 - 2^64. // So, if an option is set, we return as a character string. template SEXP Int64AsSEXP(ValueType value) { BEGIN_RCPP if (UseStringsForInt64()) { std::stringstream ss; if ((ss << value).fail()) { // This should not happen, its a bug in the code. std::string message = std::string("Error converting int64 to string, unset ") + kIntStringOptionName + " option."; Rcpp::stop(message.c_str()); } return Rcpp::CharacterVector(ss.str()); } else { return Rcpp::wrap(value); } END_RCPP } /** * extract a field from a message * * @param pointer external pointer to a message * @param name name of the field * * @return the field called "name" of the message if the * message has the field, otherwise an error is generated */ RcppExport SEXP getMessageField(SEXP pointer, SEXP name) { RPB_DEBUG_BEGIN("getMessageField") PRINT_DEBUG_INFO("pointer", pointer); PRINT_DEBUG_INFO("name", name); /* grab the Message pointer */ Rcpp::XPtr message(pointer); GPB::FieldDescriptor* field_desc = getFieldDescriptor(message, name); RPB_DEBUG_END("getMessageField"); return (extractFieldAsSEXP(message, field_desc)); } RcppExport SEXP extractFieldAsSEXP(const Rcpp::XPtr& message, const GPB::FieldDescriptor* fieldDesc) { BEGIN_RCPP const Reflection* ref = message->GetReflection(); if (fieldDesc->is_repeated()) { switch (GPB::FieldDescriptor::TypeToCppType(fieldDesc->type())) { #undef HANDLE_REPEATED_FIELD #define HANDLE_REPEATED_FIELD(TYPE, DATATYPE) \ case TYPE: \ return Rcpp::wrap(RepeatedFieldImporter(ref, *message, fieldDesc)); HANDLE_REPEATED_FIELD(CPPTYPE_INT32, GPB::int32) HANDLE_REPEATED_FIELD(CPPTYPE_DOUBLE, double) HANDLE_REPEATED_FIELD(CPPTYPE_FLOAT, float) HANDLE_REPEATED_FIELD(CPPTYPE_BOOL, bool) HANDLE_REPEATED_FIELD(CPPTYPE_ENUM, enum_field) HANDLE_REPEATED_FIELD(CPPTYPE_MESSAGE, message_field) // TODO(mstokely): Rcpp doesn't handle uint32 properly as of 2013/12 // See // https://r-forge.r-project.org/tracker/index.php?func=detail&aid=1360&group_id=155&atid=637 case CPPTYPE_UINT32: return Rcpp::wrap(UInt32RepeatedFieldImporter(ref, *message, fieldDesc)); #ifdef RCPP_HAS_LONG_LONG_TYPES // We can't handle these the same way, because Rcpp::wrap silently // casts int64s to doubles which may cause us to lose precision. case CPPTYPE_INT64: if (UseStringsForInt64()) { return Rcpp::wrap(Int64AsStringRepeatedFieldImporter(ref, *message, fieldDesc)); } else { return Rcpp::wrap(RepeatedFieldImporter(ref, *message, fieldDesc)); } case CPPTYPE_UINT64: if (UseStringsForInt64()) { return Rcpp::wrap( UInt64AsStringRepeatedFieldImporter(ref, *message, fieldDesc)); } else { return Rcpp::wrap(RepeatedFieldImporter(ref, *message, fieldDesc)); } #endif #undef HANDLE_REPEATED_FIELD case CPPTYPE_STRING: if (fieldDesc->type() == TYPE_STRING) { return Rcpp::wrap(RepeatedFieldImporter(ref, *message, fieldDesc)); } else if (fieldDesc->type() == TYPE_BYTES) { int field_size = ref->FieldSize(*message, fieldDesc); Rcpp::List res(field_size); for (int i = 0; i < field_size; i++) { std::string s = ref->GetRepeatedString(*message, fieldDesc, i); res[i] = Rcpp::wrap(std::vector(s.begin(), s.end())); } return res; } else { Rcpp::stop("unknown field type with CPP_TYPE STRING"); } default: Rcpp::stop("Unsupported type"); } } else { switch (GPB::FieldDescriptor::TypeToCppType(fieldDesc->type())) { #undef HANDLE_SINGLE_FIELD #define HANDLE_SINGLE_FIELD(CPPTYPE, SUFFIX) \ case CPPTYPE: \ return Rcpp::wrap(ref->Get##SUFFIX(*message, fieldDesc)); HANDLE_SINGLE_FIELD(CPPTYPE_INT32, Int32) HANDLE_SINGLE_FIELD(CPPTYPE_DOUBLE, Double) HANDLE_SINGLE_FIELD(CPPTYPE_FLOAT, Float) HANDLE_SINGLE_FIELD(CPPTYPE_BOOL, Bool) // TODO(mstokely): Rcpp doesn't handle uint32 properly as of 2013/12 // See // https://r-forge.r-project.org/tracker/index.php?func=detail&aid=1360&group_id=155&atid=637 case CPPTYPE_UINT32: return Rcpp::wrap(double(ref->GetUInt32(*message, fieldDesc))); #ifdef RCPP_HAS_LONG_LONG_TYPES // Handle these types separately since Rcpp::wrap doesn't // do the right thing. case CPPTYPE_INT64: return Int64AsSEXP(ref->GetInt64(*message, fieldDesc)); case CPPTYPE_UINT64: return Int64AsSEXP(ref->GetUInt64(*message, fieldDesc)); #endif #undef HANDLE_SINGLE_FIELD case CPPTYPE_STRING: if (fieldDesc->type() == TYPE_STRING) { return Rcpp::wrap(ref->GetString(*message, fieldDesc)); } else if (fieldDesc->type() == TYPE_BYTES) { std::string s = ref->GetString(*message, fieldDesc); return Rcpp::wrap(std::vector(s.begin(), s.end())); } else { Rcpp::stop("unknown field type with CPP_TYPE STRING"); } case CPPTYPE_ENUM: return Rcpp::wrap(ref->GetEnum(*message, fieldDesc)->number()); case CPPTYPE_MESSAGE: return S4_Message(CLONE(&ref->GetMessage(*message, fieldDesc))); default: Rcpp::stop("Unsupported type"); } } END_RCPP } } // namespace rprotobuf RProtoBuf/src/Rcppsupport.h0000644000176200001440000001465313164671424015456 0ustar liggesusers// rprotobuf.h: support for using Rcpp // // Copyright (C) 2010 Dirk Eddelbuettel and Romain Francois // // This file is part of RProtoBuf. // // RProtoBuf is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // RProtoBuf is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with RProtoBuf. If not, see . #ifndef RPROTOBUF__RCPPSUPPORT__H #define RPROTOBUF__RCPPSUPPORT__H #include /* for stringstream, basic_ostream */ #include /* for string */ #include "rprotobuf.h" namespace rprotobuf { /* support for Rcpp::wrap protobuf repeated fields, this essentially uses the same macro trick as in protobuf, but reversed */ struct enum_field{}; struct message_field{}; class Int64AsStringRepeatedFieldImporter { public: // Probably want to convert to strings here. typedef std::string r_import_type; Int64AsStringRepeatedFieldImporter(const GPB::Reflection* ref_ , const GPB::Message& message_, const GPB::FieldDescriptor* field_) : ref(ref_), message(message_), field(field_) {} inline int size() const { return ref->FieldSize(message, field); } inline std::string get(int i) const { std::stringstream stream; int64 val = ref->GetRepeatedInt64(message, field, i); stream << val; return stream.str(); } private: const GPB::Reflection* ref; const GPB::Message& message; const GPB::FieldDescriptor* field; }; class UInt64AsStringRepeatedFieldImporter { public: // Probably want to convert to strings here. typedef std::string r_import_type; UInt64AsStringRepeatedFieldImporter(const GPB::Reflection* ref_, const GPB::Message& message_, const GPB::FieldDescriptor* field_) : ref(ref_), message(message_), field(field_) {} inline int size() const { return ref->FieldSize(message, field) ; } inline std::string get(int i) const { std::stringstream stream; uint64 val = ref->GetRepeatedUInt64(message, field, i); stream << val; return stream.str(); } private: const GPB::Reflection* ref; const GPB::Message& message; const GPB::FieldDescriptor* field; }; // TODO(mstokely): Rcpp doesn't handle uint32 properly as of 2013/12 // See https://r-forge.r-project.org/tracker/index.php?func=detail&aid=1360&group_id=155&atid=637 class UInt32RepeatedFieldImporter { public: // Represent as doubles, since R doesn't have uint32s. typedef double r_import_type; UInt32RepeatedFieldImporter(const GPB::Reflection* ref_ , const GPB::Message& message_, const GPB::FieldDescriptor* field_) : ref(ref_), message(message_), field(field_) {} inline int size() const { return ref->FieldSize(message, field); } inline double get(int i) const { return double(ref->GetRepeatedUInt32(message, field, i)); } private: const GPB::Reflection* ref; const GPB::Message& message; const GPB::FieldDescriptor* field; }; template class RepeatedFieldImporter{} ; #undef GENERATE__FIELD__IMPORTER__DECL #define GENERATE__FIELD__IMPORTER__DECL(__TYPE__, __CAMEL__) \ template<> class RepeatedFieldImporter<__TYPE__> { \ public: \ typedef __TYPE__ r_import_type; \ RepeatedFieldImporter( \ const GPB::Reflection* ref_, \ const GPB::Message& message_, \ const GPB::FieldDescriptor* field_): \ ref(ref_), message(message_), field(field_) {} \ inline int size() const { \ return ref->FieldSize( message, field ); \ } \ inline __TYPE__ get(int i) const { \ return ref->GetRepeated##__CAMEL__(message, field, i); \ } \ private: \ const GPB::Reflection* ref; \ const GPB::Message& message; \ const GPB::FieldDescriptor* field; \ }; GENERATE__FIELD__IMPORTER__DECL(GPB::int32, Int32) GENERATE__FIELD__IMPORTER__DECL(GPB::uint32, UInt32) GENERATE__FIELD__IMPORTER__DECL(GPB::int64, Int64) GENERATE__FIELD__IMPORTER__DECL(GPB::uint64, UInt64) GENERATE__FIELD__IMPORTER__DECL(float, Float) GENERATE__FIELD__IMPORTER__DECL(double, Double) GENERATE__FIELD__IMPORTER__DECL(bool, Bool) GENERATE__FIELD__IMPORTER__DECL(std::string, String) #undef GENERATE__FIELD__IMPORTER__DECL template<> class RepeatedFieldImporter{ public: typedef int r_import_type ; RepeatedFieldImporter( const GPB::Reflection* ref_, const GPB::Message& message_, const GPB::FieldDescriptor* field_): ref(ref_), message(message_), field(field_) {}; inline int size() const { return ref->FieldSize( message, field ); } inline int get(int i) const { return ref->GetRepeatedEnum(message, field, i)->number(); } private: const GPB::Reflection* ref; const GPB::Message& message; const GPB::FieldDescriptor* field; } ; template<> class RepeatedFieldImporter{ public: typedef message_field r_import_type ; RepeatedFieldImporter( const GPB::Reflection* ref_ , const GPB::Message& message_, const GPB::FieldDescriptor* field_): ref(ref_), message(message_), field(field_) {}; inline int size() const { return ref->FieldSize( message, field ); } inline SEXP wrap(int i) const { return S4_Message(CLONE(&ref->GetRepeatedMessage(message, field, i))); } private: const GPB::Reflection* ref; const GPB::Message& message; const GPB::FieldDescriptor* field; }; } // namespace rprotobuf #endif RProtoBuf/src/wrapper_ZeroCopyInputStream.cpp0000644000176200001440000000251213164671424021145 0ustar liggesusers// -*- indent-tabs-mode: nil; tab-width: 4; show-trailing-whitespace: t; c-indent-level: 4; c-basic-offset: 4; -*- #include "rprotobuf.h" namespace rprotobuf { SEXP ZeroCopyInputStream_Next(SEXP xp) { BEGIN_RCPP GPB::io::ZeroCopyInputStream* stream = GET_ZCIS(xp); int s = 0; const void* in; bool res = stream->Next(&in, &s); Rcpp::RawVector result; if (!res) { throw std::range_error("cannot read from stream"); } else { result.assign(reinterpret_cast(in), reinterpret_cast(in) + s); } return result; END_RCPP } SEXP ZeroCopyInputStream_BackUp(SEXP xp, SEXP size) { BEGIN_RCPP GPB::io::ZeroCopyInputStream* stream = GET_ZCIS(xp); int s = GET_int(size, 0); if (s <= 0) { Rf_error("can only BackUp with positive numbers"); } stream->BackUp(s); return R_NilValue; END_RCPP } SEXP ZeroCopyInputStream_Skip(SEXP xp, SEXP size) { BEGIN_RCPP GPB::io::ZeroCopyInputStream* stream = GET_ZCIS(xp); int s = GET_int(size, 0); bool res = stream->Skip(s); return (Rf_ScalarLogical(res ? _TRUE_ : _FALSE_)); END_RCPP } SEXP ZeroCopyInputStream_ByteCount(SEXP xp) { BEGIN_RCPP GPB::io::ZeroCopyInputStream* stream = GET_ZCIS(xp); return (Rf_ScalarReal((double)stream->ByteCount())); END_RCPP } } RProtoBuf/src/RWarningErrorCollector.cpp0000644000176200001440000000073013164671424020047 0ustar liggesusers// -*- indent-tabs-mode: nil; tab-width: 4; show-trailing-whitespace: t; c-indent-level: 4; c-basic-offset: 4; -*- #include "rprotobuf.h" #include "RWarningErrorCollector.h" namespace rprotobuf { void RWarningErrorCollector::AddError(const std::string& filename, int line, int column, const std::string& message) { Rprintf("%s:%d:%d:%s\n", filename.c_str(), line + 1, column + 1, message.c_str()); } } // namespace rprotobuf RProtoBuf/src/wrapper_EnumDescriptor.cpp0000644000176200001440000001043313164671424020143 0ustar liggesusers// -*- indent-tabs-mode: nil; tab-width: 4; show-trailing-whitespace: t; c-indent-level: 4; c-basic-offset: 4; -*- // wrapper_EnumDescriptor.cpp: R/C++ interface class library // // Copyright (C) 2010 - 2011 Dirk Eddelbuettel and Romain Francois // // This file is part of RProtoBuf. // // RProtoBuf is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // RProtoBuf is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with RProtoBuf. If not, see . #include "rprotobuf.h" #include "RcppMacros.h" namespace rprotobuf { #undef METHOD #define METHOD(__NAME__) RCPP_PP_CAT(EnumDescriptor__, __NAME__) RPB_XP_METHOD_0(METHOD(as_character), GPB::EnumDescriptor, DebugString) RPB_XP_METHOD_0(METHOD(length), GPB::EnumDescriptor, value_count) RPB_XP_METHOD_0(METHOD(value_count), GPB::EnumDescriptor, value_count) RPB_FUNCTION_1(S4_Descriptor, METHOD(containing_type), Rcpp::XPtr d) { return S4_Descriptor(d->containing_type()); } RPB_FUNCTION_2(SEXP, METHOD(getValueByIndex), Rcpp::XPtr d, int index) { if ((index >= 0) && (index < d->value_count())) { return S4_EnumValueDescriptor(d->value(index)); } else { return R_NilValue; } } RPB_FUNCTION_2(SEXP, METHOD(getValueByNumber), Rcpp::XPtr d, int i) { const GPB::EnumValueDescriptor* descriptor = d->FindValueByNumber(i); if (descriptor) return S4_EnumValueDescriptor(descriptor); return R_NilValue; } RPB_FUNCTION_2(SEXP, METHOD(getValueByName), Rcpp::XPtr d, std::string name) { const GPB::EnumValueDescriptor* descriptor = d->FindValueByName(name); if (descriptor) return S4_EnumValueDescriptor(descriptor); return R_NilValue; } RPB_FUNCTION_1(S4_Message, METHOD(as_Message), Rcpp::XPtr d) { GPB::EnumDescriptorProto* message = new GPB::EnumDescriptorProto(); d->CopyTo(message); return S4_Message(message); } /** * Get the value of the enum called name * * @param xp external pointer to an EnumDescriptor * @param name the name of the enum * * @param the value associated with the name */ RPB_FUNCTION_2(int, get_value_of_enum, Rcpp::XPtr d, std::string name) { const GPB::EnumValueDescriptor* evd = d->FindValueByName(name); if (!evd) { /* or maybe it should just be NA */ Rcpp::stop("cannot get the value"); } return evd->number(); } /** * Does enum have value named 'name'? * * @param xp external pointer to an EnumDescriptor * @param name the name of the enum * @return logical */ RPB_FUNCTION_2(bool, has_enum_name, Rcpp::XPtr d, std::string name) { const GPB::EnumValueDescriptor* evd = d->FindValueByName(name); return (evd != NULL); } /** * @param xp external pointer to a Descriptor * @return the descriptor as an R list */ RPB_FUNCTION_1(Rcpp::List, METHOD(as_list), Rcpp::XPtr d) { int n = d->value_count(); Rcpp::CharacterVector names(n); Rcpp::List res(n); for (int i = 0; i < n; i++) { const GPB::EnumValueDescriptor* value_d = d->value(i); res[i] = value_d->number(); names[i] = value_d->name(); } res.names() = names; return res; } RPB_FUNCTION_1(Rcpp::CharacterVector, METHOD(getConstantNames), Rcpp::XPtr d) { int n = d->value_count(); Rcpp::CharacterVector res(n); for (int i = 0; i < n; i++) { res[i] = d->value(i)->name(); } return res; } RPB_FUNCTION_1(S4_FileDescriptor, METHOD(fileDescriptor), Rcpp::XPtr desc) { return S4_FileDescriptor(desc->file()); } RPB_FUNCTION_2(std::string, METHOD(name), Rcpp::XPtr d, bool full) { return full ? d->full_name() : d->name(); } #undef METHOD } // namespace rprotobuf RProtoBuf/src/rprotobuf.h0000644000176200001440000002225413164671424015133 0ustar liggesusers// rprotobuf.h: R/C++ interface class library // // Copyright (C) 2009-2012 Dirk Eddelbuettel and Romain Francois // Copyright (C) 2012-2013 Dirk Eddelbuettel, Romain Francois and Murray Stokely // // This file is part of RProtoBuf. // // RProtoBuf is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // RProtoBuf is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with RProtoBuf. If not, see . #ifndef RPROTOBUF_H #define RPROTOBUF_H // TODO(mstokely): should we check if this header is available? #include #include // for strerror #include // g++-4.7 wants this #include // for string // O_BINARY does not exist on Unix/Linux, since there is no distinction // between text mode and binary mode files there, but if we ever got // this code running on Windows this would be needed. #ifndef O_BINARY #define O_BINARY 0 #endif #include #include #include #include #include #include #include #include #include namespace GPB = google::protobuf; #define R_NO_REMAP /* we need to read and write to connections */ #define NEED_CONNECTION_PSTREAMS #include RCPP_ENUM_TRAITS(GPB::FieldDescriptor::Label) RCPP_ENUM_TRAITS(GPB::FieldDescriptor::CppType) RCPP_ENUM_TRAITS(GPB::FieldDescriptor::Type) // RCPP_TRAITS(GPB::int64,REALSXP) // RCPP_TRAITS(GPB::uint64,REALSXP) #include #include #include /* uncomment for debugging */ // #define RPB_DEBUG #ifdef RPB_DEBUG #define RPB_DEBUG_BEGIN(__WHAT__) Rprintf("<" #__WHAT__ ">\n"); #define RPB_DEBUG_END(__WHAT__) Rprintf("\n"); #else #define RPB_DEBUG_BEGIN(__WHAT__) #define RPB_DEBUG_END(__WHAT__) #endif // #define FIN_DBG(ptr, CLAZZ) // #define FIN_DBG(ptr, CLAZZ) Rprintf( "RProtoBuf finalizing %s (%p)\n", CLAZZ, // ptr ) #ifdef RPB_DEBUG #define PRINT_DEBUG_INFO(name, o) \ Rprintf(" %s [%d] = ", name, TYPEOF(o)); \ Rf_PrintValue(o); #else #define PRINT_DEBUG_INFO(name, o) #endif #define RPROTOBUF_LOOKUP 24 // #define LOOKUP_DEBUG /* FIXME : quick hack because just using TRUE and FALSE did not work in * lookup.cpp */ #define _TRUE_ (Rboolean) TRUE #define _FALSE_ (Rboolean) FALSE #define GET_MESSAGE_POINTER_FROM_XP(xp) (GPB::Message*) EXTPTR_PTR(xp) #define GET_MESSAGE_POINTER_FROM_S4(m) \ (GPB::Message*) EXTPTR_PTR(GET_SLOT(m, Rf_install("pointer"))) #define GET_DESCRIPTOR_POINTER_FROM_XP(xp) (GPB::Descriptor*) EXTPTR_PTR(xp) #define GET_DESCRIPTOR_POINTER_FROM_S4(m) \ (GPB::Descriptor*) EXTPTR_PTR(GET_SLOT(m, Rf_install("pointer"))) #define GET_FIELD_DESCRIPTOR_POINTER_FROM_XP(xp) (GPB::FieldDescriptor*) EXTPTR_PTR(xp) #define GET_FIELD_DESCRIPTOR_POINTER_FROM_S4(m) \ (GPB::FieldDescriptor*) EXTPTR_PTR(GET_SLOT(m, Rf_install("pointer"))) #define GET_ENUM_VALUE_DESCRIPTOR_POINTER_FROM_XP(xp) (GPB::EnumValueDescriptor*) EXTPTR_PTR(xp) #define GET_ENUM_VALUE_DESCRIPTOR_POINTER_FROM_S4(m) \ (GPB::EnumValueDescriptor*) EXTPTR_PTR(GET_SLOT(m, Rf_install("pointer"))) #define COPYSTRING(s) s #define THROW_SOCKET_ERROR(message) Rf_error("%s : %s", message, strerror(sockerrno)) #define XPP EXTPTR_PTR #define NEW_S4_OBJECT(CLAZZ) \ SEXP oo = PROTECT(NEW_OBJECT(MAKE_CLASS(CLAZZ))); \ if (!Rf_inherits(oo, CLAZZ)) Rcpp::stop(CLAZZ); namespace rprotobuf { typedef GPB::int32 int32; typedef GPB::uint32 uint32; typedef GPB::int64 int64; typedef GPB::uint64 uint64; /* in rprotobuf.cpp */ GPB::Message* PROTOTYPE(const GPB::Descriptor*); GPB::Message* CLONE(const GPB::Message*); RcppExport SEXP do_dollar_Descriptor(SEXP, SEXP); RcppExport SEXP newProtoMessage(SEXP); RcppExport SEXP getProtobufDescriptor(SEXP); RcppExport SEXP getExtensionDescriptor(SEXP); RcppExport SEXP readProtoFiles_cpp(SEXP, SEXP); RcppExport Rboolean isMessage(SEXP, const char*); RcppExport GPB::FieldDescriptor* getFieldDescriptor(const GPB::Message*, SEXP); /* in extractors.cpp */ RcppExport SEXP getMessageField(SEXP, SEXP); RcppExport SEXP extractFieldAsSEXP(const Rcpp::XPtr&, const GPB::FieldDescriptor*); /* in lookup.cpp */ RcppExport SEXP newProtocolBufferLookup(SEXP); /* in mutators.cpp */ RcppExport SEXP setMessageField(SEXP, SEXP, SEXP); int GET_int(SEXP, int); double GET_double(SEXP, int); float GET_float(SEXP, int); int32 GET_int32(SEXP, R_xlen_t); int64 GET_int64(SEXP, R_xlen_t); uint32 GET_uint32(SEXP, R_xlen_t); uint64 GET_uint64(SEXP, R_xlen_t); bool GET_bool(SEXP, R_xlen_t); std::string GET_stdstring(SEXP, R_xlen_t); std::string GET_bytes(SEXP, R_xlen_t); void CHECK_values_for_enum(const GPB::FieldDescriptor*, SEXP); void CHECK_messages(const GPB::FieldDescriptor*, SEXP); /* in wrapper_ServiceDescriptor.cpp */ RcppExport SEXP ServiceDescriptor_length(SEXP); RcppExport SEXP ServiceDescriptor_method_count(SEXP); RcppExport SEXP ServiceDescriptor_getMethodByIndex(SEXP, SEXP); RcppExport SEXP ServiceDescriptor_getMethodByName(SEXP, SEXP); /* in streams.cpp */ void ZeroCopyInputStreamWrapper_finalizer(SEXP); void ZeroCopyOutputStreamWrapper_finalizer(SEXP); RcppExport SEXP ZeroCopyInputStream_Next(SEXP); RcppExport SEXP ZeroCopyInputStream_BackUp(SEXP, SEXP); RcppExport SEXP ZeroCopyInputStream_ByteCount(SEXP); RcppExport SEXP ZeroCopyInputStream_Skip(SEXP, SEXP); RcppExport SEXP ZeroCopyInputStream_ReadRaw(SEXP, SEXP); RcppExport SEXP ZeroCopyInputStream_ReadString(SEXP, SEXP); RcppExport SEXP ZeroCopyInputStream_ReadVarint32(SEXP); RcppExport SEXP ZeroCopyInputStream_ReadVarint64(SEXP); RcppExport SEXP ZeroCopyInputStream_ReadLittleEndian32(SEXP); RcppExport SEXP ZeroCopyInputStream_ReadLittleEndian64(SEXP); RcppExport SEXP ZeroCopyOutputStream_Next(SEXP, SEXP); RcppExport SEXP ZeroCopyOutputStream_BackUp(SEXP, SEXP); RcppExport SEXP ZeroCopyOutputStream_ByteCount(SEXP); RcppExport SEXP ZeroCopyOutputStream_WriteRaw(SEXP, SEXP); RcppExport SEXP ZeroCopyOutputStream_WriteString(SEXP, SEXP); RcppExport SEXP ZeroCopyOutputStream_WriteLittleEndian32(SEXP, SEXP); RcppExport SEXP ZeroCopyOutputStream_WriteLittleEndian64(SEXP, SEXP); RcppExport SEXP ZeroCopyOutputStream_WriteVarint32(SEXP, SEXP); RcppExport SEXP ZeroCopyOutputStream_WriteVarint64(SEXP, SEXP); RcppExport SEXP FileOutputStream_new(SEXP, SEXP, SEXP); RcppExport SEXP FileOutputStream_Close(SEXP); RcppExport SEXP FileOutputStream_Flush(SEXP); RcppExport SEXP FileOutputStream_GetErrno(SEXP); RcppExport SEXP FileOutputStream_SetCloseOnDelete(SEXP, SEXP); RcppExport SEXP FileInputStream_new(SEXP, SEXP, SEXP); RcppExport SEXP FileInputStream_Close(SEXP); RcppExport SEXP FileInputStream_GetErrno(SEXP); RcppExport SEXP FileInputStream_SetCloseOnDelete(SEXP, SEXP); RcppExport SEXP ConnectionInputStream_new(SEXP, SEXP); RcppExport SEXP ConnectionOutputStream_new(SEXP, SEXP); /** * simple class that wraps together a ZeroCopyOutputStream * and its associated CodedOutputStream. Since we don't expose * CodedOutputStream at the R level, this allows to keep only one such * object with each ZeroCopyOutputStream */ class ZeroCopyOutputStreamWrapper { public: ZeroCopyOutputStreamWrapper(GPB::io::ZeroCopyOutputStream* stream); ~ZeroCopyOutputStreamWrapper(); GPB::io::ZeroCopyOutputStream* get_stream(); GPB::io::CodedOutputStream* get_coded_stream(); private: GPB::io::ZeroCopyOutputStream* stream; GPB::io::CodedOutputStream* coded_stream; }; /** * simple class that wraps together a ZeroCopyInputStream * and its associated CodedInputStream. Since we don't expose * CodedInputStream at the R level, this allows to keep only one such * object with each zero copy input stream */ class ZeroCopyInputStreamWrapper { public: ZeroCopyInputStreamWrapper(GPB::io::ZeroCopyInputStream* stream); ~ZeroCopyInputStreamWrapper(); GPB::io::ZeroCopyInputStream* get_stream(); GPB::io::CodedInputStream* get_coded_stream(); private: GPB::io::ZeroCopyInputStream* stream; GPB::io::CodedInputStream* coded_stream; }; } // namespace rprotobuf #include "S4_classes.h" #include "RconnectionCopyingInputStream.h" #define GET_ZCIS(xp) ((ZeroCopyInputStreamWrapper*)XPP(xp))->get_stream() #define GET_CIS(xp) ((ZeroCopyInputStreamWrapper*)XPP(xp))->get_coded_stream() #define GET_FIS(xp) (GPB::io::FileInputStream*)((ZeroCopyInputStreamWrapper*)XPP(xp))->get_stream() #define GET_ZCOS(xp) ((ZeroCopyOutputStreamWrapper*)XPP(xp))->get_stream() #define GET_COS(xp) ((ZeroCopyOutputStreamWrapper*)XPP(xp))->get_coded_stream() #define GET_FOS(xp) \ (GPB::io::FileOutputStream*)((ZeroCopyOutputStreamWrapper*)XPP(xp))->get_stream() #endif RProtoBuf/src/S4_classes.h0000644000176200001440000001704113164671424015112 0ustar liggesusers// S4_classes.h: R/C++ interface class library // // Copyright (C) 2010 - 2017 Dirk Eddelbuettel and Romain Francois // // This file is part of RProtoBuf. // // RProtoBuf is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // RProtoBuf is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with RProtoBuf. If not, see . #ifndef RPROTOBUF_S4CLASSES_H #define RPROTOBUF_S4CLASSES_H //1. Place using Rcpp::S4; somewhere in the top of S4_classes.h in the //src directory (so S4 is looked up in the right place), //2. Replace setSEXP with set__, and asSexp with get__. namespace rprotobuf { // deal with Rcpp API changes #if defined(RCPP_VERSION) && RCPP_VERSION <= Rcpp_Version(0,10,6) #define SetSexp setSEXP #define AsSexp asSexp #else #define SetSexp set__ #define AsSexp get__ #endif using Rcpp::S4; class ZeroCopyInputStreamWrapper; class ZeroCopyOutputStreamWrapper; class S4_EnumValueDescriptor : public Rcpp::S4 { public: S4_EnumValueDescriptor(const GPB::EnumValueDescriptor* d) : S4("EnumValueDescriptor") { slot("pointer") = Rcpp::XPtr( const_cast(d), false); if (d) { slot("name") = d->name(); slot("full_name") = d->full_name(); } else { slot("name") = Rcpp::StringVector(0); slot("full_name") = Rcpp::StringVector(0); } } S4_EnumValueDescriptor(const S4_EnumValueDescriptor& other) : S4() { SetSexp(other.AsSexp()); } S4_EnumValueDescriptor& operator=(const S4_EnumValueDescriptor& other) { SetSexp(other.AsSexp()); return *this; } }; class S4_Descriptor : public Rcpp::S4 { public: S4_Descriptor(const GPB::Descriptor* d) : S4("Descriptor") { slot("pointer") = Rcpp::XPtr(const_cast(d), false); if (!d) { slot("type") = Rcpp::StringVector(0); } else { slot("type") = d->full_name(); } } S4_Descriptor(const S4_Descriptor& other) : S4() { SetSexp(other.AsSexp()); } S4_Descriptor& operator=(const S4_Descriptor& other) { SetSexp(other.AsSexp()); return *this; } }; class S4_FileDescriptor : public Rcpp::S4 { public: S4_FileDescriptor(const GPB::FileDescriptor* d) : S4("FileDescriptor") { slot("pointer") = Rcpp::XPtr(const_cast(d), false); if (!d) { slot("package") = Rcpp::StringVector(0); slot("filename") = Rcpp::StringVector(0); } else { slot("package") = d->package(); slot("filename") = d->name(); } } S4_FileDescriptor(const S4_FileDescriptor& other) : S4() { SetSexp(other.AsSexp()); } S4_FileDescriptor& operator=(const S4_FileDescriptor& other) { SetSexp(other.AsSexp()); return *this; } }; class S4_FieldDescriptor : public Rcpp::S4 { public: S4_FieldDescriptor(const GPB::FieldDescriptor* d) : S4("FieldDescriptor") { slot("pointer") = Rcpp::XPtr(const_cast(d), false); slot("name") = d->name(); slot("full_name") = d->full_name(); slot("type") = d->containing_type()->full_name(); } S4_FieldDescriptor(const S4_FieldDescriptor& other) : S4() { SetSexp(other.AsSexp()); } S4_FieldDescriptor& operator=(const S4_FieldDescriptor& other) { SetSexp(other.AsSexp()); return *this; } }; class S4_ServiceDescriptor : public Rcpp::S4 { public: S4_ServiceDescriptor(const GPB::ServiceDescriptor* d) : S4("ServiceDescriptor") { slot("pointer") = Rcpp::XPtr(const_cast(d), false); } S4_ServiceDescriptor(const S4_ServiceDescriptor& other) : S4() { SetSexp(other.AsSexp()); } S4_ServiceDescriptor& operator=(const S4_ServiceDescriptor& other) { SetSexp(other.AsSexp()); return *this; } }; class S4_MethodDescriptor : public Rcpp::S4 { public: S4_MethodDescriptor(const GPB::MethodDescriptor* d) : S4("MethodDescriptor") { slot("pointer") = Rcpp::XPtr(const_cast(d), false); } S4_MethodDescriptor(const S4_MethodDescriptor& other) : S4() { SetSexp(other.AsSexp()); } S4_MethodDescriptor& operator=(const S4_MethodDescriptor& other) { SetSexp(other.AsSexp()); return *this; } }; class S4_EnumDescriptor : public Rcpp::S4 { public: S4_EnumDescriptor(const GPB::EnumDescriptor* d) : S4("EnumDescriptor") { slot("pointer") = Rcpp::XPtr(const_cast(d), false); slot("type") = Rcpp::StringVector(0); if (d) { slot("name") = d->name(); slot("full_name") = d->full_name(); const GPB::Descriptor* type_desc = d->containing_type(); if (type_desc) { slot("type") = type_desc->full_name(); } } else { slot("name") = Rcpp::StringVector(0); slot("full_name") = Rcpp::StringVector(0); } } S4_EnumDescriptor(const S4_EnumDescriptor& other) : S4() { SetSexp(other.AsSexp()); } S4_EnumDescriptor& operator=(const S4_EnumDescriptor& other) { SetSexp(other.AsSexp()); return *this; } }; class S4_Message : public Rcpp::S4 { public: S4_Message(const GPB::Message* d) : S4("Message") { slot("pointer") = Rcpp::XPtr(const_cast(d), true); slot("type") = d->GetDescriptor()->full_name(); } S4_Message(const S4_Message& other) : S4() { SetSexp(other.AsSexp()); } S4_Message& operator=(const S4_Message& other) { SetSexp(other.AsSexp()); return *this; } }; class S4_ArrayOutputStream : public Rcpp::S4 { public: S4_ArrayOutputStream(int size, int block_size) : S4("ArrayOutputStream") { Rcpp::RawVector payload(size); GPB::io::ArrayOutputStream* stream = new GPB::io::ArrayOutputStream(payload.begin(), size, block_size); Rcpp::XPtr wrapper(new ZeroCopyOutputStreamWrapper(stream), true, R_NilValue, payload); slot("pointer") = wrapper; } S4_ArrayOutputStream(const S4_ArrayOutputStream& other) : S4(other) { SetSexp(other.AsSexp()); } S4_ArrayOutputStream& operator=(const S4_ArrayOutputStream& other) { SetSexp(other.AsSexp()); return *this; } }; class S4_ArrayInputStream : public Rcpp::S4 { public: S4_ArrayInputStream(Rcpp::RawVector payload, int block_size) : S4("ArrayInputStream") { GPB::io::ArrayInputStream* stream = new GPB::io::ArrayInputStream(payload.begin(), payload.size(), block_size); Rcpp::XPtr wrapper( new ZeroCopyInputStreamWrapper(stream), true, R_NilValue, payload); slot("pointer") = wrapper; } }; #undef SetSexp #undef AsSexp } // namespace rprotobuf #endif RProtoBuf/src/RconnectionCopyingInputStream.cpp0000644000176200001440000000217213164671424021447 0ustar liggesusers// -*- indent-tabs-mode: nil; tab-width: 4; show-trailing-whitespace: t; c-indent-level: 4; c-basic-offset: 4; -*- #include "rprotobuf.h" #include "RconnectionCopyingInputStream.h" namespace rprotobuf { /* N.B. connection must be opened in binary mode due to call * to readBin below. */ RconnectionCopyingInputStream::RconnectionCopyingInputStream(int id) : connection_id(id), failure(false) {} /** * call readBin to read size bytes from R * * @param buffer buffer to fill with at most size bytes * @param size maximum number of bytes * * @return the number of bytes actually read */ int RconnectionCopyingInputStream::Read(void* buffer, int size) { Rcpp::Language call("readBin", connection_id, Rcpp::RawVector(0), size); Rcpp::RawVector res; try { res = call.eval(); } catch (...) { /* Failed to read anything from the connection, * could have been permissions, or connection opened * in the wrong type, etc. */ failure = true; return -1; } int len = res.size(); memcpy(buffer, reinterpret_cast(res.begin()), len); return len; } } RProtoBuf/src/rprotobuf.cpp0000644000176200001440000002031213164671424015457 0ustar liggesusers// -*- indent-tabs-mode: nil; tab-width: 4; show-trailing-whitespace: t; c-indent-level: 4; c-basic-offset: 4; -*- #include "rprotobuf.h" #include "DescriptorPoolLookup.h" #include "RcppMacros.h" namespace rprotobuf { GPB::Message* PROTOTYPE(const GPB::Descriptor* desc) { RPB_DEBUG_BEGIN("PROTOTYPE") #ifdef RPB_DEBUG Rprintf("desc = %d\n", desc); #endif /* first try the runtime factory */ GPB::Message* m = (GPB::Message*)((GPB::DynamicMessageFactory*)DescriptorPoolLookup::factory()) ->GetPrototype(desc) ->New(); #ifdef RPB_DEBUG Rprintf("generated factory = %d\n", m); #endif if (!m) { /* then the dynamic runtime factory */ m = (GPB::Message*)GPB::MessageFactory::generated_factory()->GetPrototype(desc)->New(); #ifdef RPB_DEBUG Rprintf("runtime factory = %d\n", m); #endif } RPB_DEBUG_END("PROTOTYPE") return m; } GPB::Message* CLONE(const GPB::Message* origin) { RPB_DEBUG_BEGIN("CLONE") const GPB::Descriptor* desc = origin->GetDescriptor(); GPB::Message* sheep = PROTOTYPE(desc); sheep->CopyFrom(*origin); RPB_DEBUG_END("CLONE") return sheep; } /** * read a proto file and cache the message definitions it contains * * @param file proto file name */ RcppExport SEXP readProtoFiles_cpp(SEXP file, SEXP dirs) { BEGIN_RCPP DescriptorPoolLookup::importProtoFiles(file, dirs); return R_NilValue; END_RCPP } /** * get the descriptor associated with a message type * * @param type message type * * @return an S4 object of class Descriptor, or NULL if the type * is unknown */ RcppExport SEXP getProtobufDescriptor(SEXP type) { #ifdef RPB_DEBUG Rprintf("\n type = "); Rf_PrintValue(type); #endif const char* typeName = CHAR(STRING_ELT(type, 0)); /* first try the generated pool */ const GPB::DescriptorPool* pool = GPB::DescriptorPool::generated_pool(); const GPB::Descriptor* desc = pool->FindMessageTypeByName(typeName); if (!desc) { /* then try the "runtime" pool" */ pool = DescriptorPoolLookup::pool(); desc = pool->FindMessageTypeByName(typeName); if (!desc) { /* unlucky */ return R_NilValue; } } return (S4_Descriptor(desc)); } /** * get the descriptor associated with an extension * * @param type message type * * @return an S4 object of class FieldDescriptor, or NULL if the type * is unknown */ RcppExport SEXP getExtensionDescriptor(SEXP type) { #ifdef RPB_DEBUG Rprintf("\n type = "); Rf_PrintValue(type); #endif const char* typeName = CHAR(STRING_ELT(type, 0)); /* first try the generated pool */ const GPB::DescriptorPool* pool = GPB::DescriptorPool::generated_pool(); const GPB::FieldDescriptor* desc = pool->FindExtensionByName(typeName); if (!desc) { /* then try the "runtime" pool" */ pool = DescriptorPoolLookup::pool(); desc = pool->FindExtensionByName(typeName); if (!desc) { /* unlucky */ return R_NilValue; } } return (S4_FieldDescriptor(desc)); } /** * get the descriptor associated with an enum * * @param type message type * * @return an S4 object of class EnumDescriptor, or NULL if the type * is unknown */ RcppExport SEXP getEnumDescriptor(SEXP type) { #ifdef RPB_DEBUG Rprintf("\n type = "); Rf_PrintValue(type); #endif const char* typeName = CHAR(STRING_ELT(type, 0)); /* first try the generated pool */ const GPB::DescriptorPool* pool = GPB::DescriptorPool::generated_pool(); const GPB::EnumDescriptor* desc = pool->FindEnumTypeByName(typeName); if (!desc) { /* then try the "runtime" pool" */ pool = DescriptorPoolLookup::pool(); desc = pool->FindEnumTypeByName(typeName); if (!desc) { /* unlucky */ return R_NilValue; } } return (S4_EnumDescriptor(desc)); } /** * make a new protobuf message * * @param descriptor a "Descriptor" R object */ SEXP newProtoMessage(SEXP descriptor) { BEGIN_RCPP RPB_DEBUG_BEGIN("newProtoMessage") #ifdef RPB_DEBUG /* FIXME: the message type, we don't really need that*/ SEXP type = GET_SLOT(descriptor, Rf_install("type")); #endif /* the pointer to the c++ descriptor object */ GPB::Descriptor* desc = GET_DESCRIPTOR_POINTER_FROM_S4(descriptor); #ifdef RPB_DEBUG Rprintf("desc = %d\n", desc); PRINT_DEBUG_INFO("type", type); #endif /* grab the Message from the factory */ const GPB::Message* message = PROTOTYPE(desc); if (!message) { Rcpp_error("could not call factory->GetPrototype(desc)->New()"); } RPB_DEBUG_END("newProtoMessage") return (S4_Message(message)); END_RCPP } /** * dollar extractor for Descriptor objects * it may return a Field descriptor or a nested type descriptor * * @param pointer external pointer to a google::protobuf::Descriptor object * @param name name of the thing to extract */ RcppExport SEXP do_dollar_Descriptor(SEXP pointer, SEXP name) { const char* what = CHAR(STRING_ELT(name, 0)); GPB::Descriptor* desc = (GPB::Descriptor*)EXTPTR_PTR(pointer); // trying fields first : if (desc->field_count()) { const GPB::FieldDescriptor* fd = desc->FindFieldByName(what); if (fd) { return (S4_FieldDescriptor(fd)); } } // now trying nested types if (desc->nested_type_count()) { const GPB::Descriptor* d = desc->FindNestedTypeByName(what); if (d) { return (S4_Descriptor(d)); } } // now for enum types if (desc->enum_type_count()) { const GPB::EnumDescriptor* ed = desc->FindEnumTypeByName(what); if (ed) { return (S4_EnumDescriptor(ed)); } } // TODO: extensions (later) // give up // TODO: should this be unbound instead return (R_NilValue); } /** * * @param m potentially a message * @param target the expected type * * @return TRUE if m is a a message of the given type */ Rboolean isMessage(SEXP m, const char* target) { RPB_DEBUG_BEGIN("isMessage") if (TYPEOF(m) != S4SXP || !Rf_inherits(m, "Message")) return _FALSE_; GPB::Message* message = (GPB::Message*)EXTPTR_PTR(GET_SLOT(m, Rf_install("pointer"))); const char* type = message->GetDescriptor()->full_name().c_str(); RPB_DEBUG_END("isMessage") if (strcmp(type, target)) { return _FALSE_; } return _TRUE_; } RcppExport GPB::FieldDescriptor* getFieldDescriptor(const GPB::Message* message, SEXP name) { GPB::FieldDescriptor* field_desc = (GPB::FieldDescriptor*)0; BEGIN_RCPP const GPB::Descriptor* desc = message->GetDescriptor(); std::string error_message = "could not get FieldDescriptor for field"; switch (TYPEOF(name)) { case S4SXP: { if (Rf_inherits(name, "FieldDescriptor")) { field_desc = GET_FIELD_DESCRIPTOR_POINTER_FROM_S4(name); } else { Rcpp::stop("S4 class is not a FieldDescriptor"); } break; } case CHARSXP: { field_desc = (GPB::FieldDescriptor*)desc->FindFieldByName(CHAR(name)); error_message = error_message + " '" + CHAR(name) + "'"; break; } case STRSXP: { field_desc = (GPB::FieldDescriptor*)desc->FindFieldByName(CHAR(STRING_ELT(name, 0))); error_message = error_message + " '" + CHAR(STRING_ELT(name, 0)) + "'"; break; } case REALSXP: case INTSXP: { field_desc = (GPB::FieldDescriptor*)desc->FindFieldByNumber(Rcpp::as(name)); break; } } if (!field_desc) { Rcpp::stop(error_message.c_str()); } return field_desc; VOID_END_RCPP return field_desc; } RPB_FUNCTION_VOID_1(check_libprotobuf_version, int minversion) { if (GOOGLE_PROTOBUF_VERSION < minversion) { throw std::range_error( "The protobuf library you are using is too old for this package, " "please upgrade"); } } RPB_FUNCTION_0(int, get_protobuf_library_version) { return GOOGLE_PROTOBUF_VERSION; } } // namespace rprotobuf RProtoBuf/src/RcppMacros.h0000644000176200001440000001642613164671424015166 0ustar liggesusers/* * Copyright 2013 Google Inc. All Rights Reserved. * Author: Murray Stokely * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. * */ /* * This file contains macros for taking C++ functions that expect * native C++ types, automatically generating new stub functions that * take SEXPs and call the appropriate Rcpp conversion functions * before calling the original function. It is based on slightly more * complex macros that were originally in Rcpp but have been * deprecated. * * In the future, Rcpp Modules would likely be a better more modern * way to implement RProtoBuf. */ #ifndef RPROTOBUF_RCPP_MACROS_H #define RPROTOBUF_RCPP_MACROS_H #include // RCPP_DECORATE, BEGIN_RCPP, END_RCPP #define RPB_FUNCTION_0(__OUT__,__NAME__) \ __OUT__ RCPP_DECORATE(__NAME__)(); \ extern "C" SEXP __NAME__(){ \ SEXP res = R_NilValue ; \ BEGIN_RCPP \ res = ::Rcpp::wrap( RCPP_DECORATE(__NAME__)() ) ; \ return res ; \ END_RCPP \ } \ __OUT__ RCPP_DECORATE(__NAME__)() #define RPB_FUNCTION_1(__OUT__,__NAME__, ___0) \ __OUT__ RCPP_DECORATE(__NAME__)(___0); \ extern "C" SEXP __NAME__(SEXP x0){ \ SEXP res = R_NilValue ; \ BEGIN_RCPP \ res = ::Rcpp::wrap( RCPP_DECORATE(__NAME__)(::Rcpp::internal::converter( x0 )) ) ; \ return res ; \ END_RCPP \ } \ __OUT__ RCPP_DECORATE(__NAME__)(___0) #define RPB_FUNCTION_2(__OUT__,__NAME__, ___0, ___1) \ __OUT__ RCPP_DECORATE(__NAME__)(___0, ___1); \ extern "C" SEXP __NAME__(SEXP x0, SEXP x1){ \ SEXP res = R_NilValue ; \ BEGIN_RCPP \ res = ::Rcpp::wrap( RCPP_DECORATE(__NAME__)(::Rcpp::internal::converter( x0 ), ::Rcpp::internal::converter( x1 )) ) ; \ return res ; \ END_RCPP \ } \ __OUT__ RCPP_DECORATE(__NAME__)(___0, ___1) #define RPB_FUNCTION_3(__OUT__,__NAME__, ___0, ___1, ___2) \ __OUT__ RCPP_DECORATE(__NAME__)(___0, ___1, ___2); \ extern "C" SEXP __NAME__(SEXP x0, SEXP x1, SEXP x2){ \ SEXP res = R_NilValue ; \ BEGIN_RCPP \ res = ::Rcpp::wrap( RCPP_DECORATE(__NAME__)(::Rcpp::internal::converter( x0 ), ::Rcpp::internal::converter( x1 ), ::Rcpp::internal::converter( x2 )) ) ; \ return res ; \ END_RCPP \ } \ __OUT__ RCPP_DECORATE(__NAME__)(___0, ___1, ___2) #define RPB_FUNCTION_VOID_1(__NAME__, ___0) \ void RCPP_DECORATE(__NAME__)(___0); \ extern "C" SEXP __NAME__(SEXP x0){ \ BEGIN_RCPP \ RCPP_DECORATE(__NAME__)(::Rcpp::internal::converter( x0 )); \ END_RCPP \ } \ void RCPP_DECORATE(__NAME__)(___0) #define RPB_FUNCTION_VOID_2(__NAME__, ___0, ___1) \ void RCPP_DECORATE(__NAME__)(___0, ___1); \ extern "C" SEXP __NAME__(SEXP x0, SEXP x1){ \ BEGIN_RCPP \ RCPP_DECORATE(__NAME__)(::Rcpp::internal::converter( x0 ), ::Rcpp::internal::converter( x1 )); \ END_RCPP \ } \ void RCPP_DECORATE(__NAME__)(___0, ___1) #define RPB_FUNCTION_VOID_3(__NAME__, ___0, ___1, ___2) \ void RCPP_DECORATE(__NAME__)(___0, ___1, ___2); \ extern "C" SEXP __NAME__(SEXP x0, SEXP x1, SEXP x2){ \ BEGIN_RCPP \ RCPP_DECORATE(__NAME__)(::Rcpp::internal::converter( x0 ), ::Rcpp::internal::converter( x1 ), ::Rcpp::internal::converter( x2 )); \ END_RCPP \ } \ void RCPP_DECORATE(__NAME__)(___0, ___1, ___2) #define RPB_FUNCTION_VOID_4(__NAME__, ___0, ___1, ___2, ___3) \ void RCPP_DECORATE(__NAME__)(___0, ___1, ___2, ___3); \ extern "C" SEXP __NAME__(SEXP x0, SEXP x1, SEXP x2, SEXP x3){ \ BEGIN_RCPP \ RCPP_DECORATE(__NAME__)(::Rcpp::internal::converter( x0 ), ::Rcpp::internal::converter( x1 ), ::Rcpp::internal::converter( x2 ), ::Rcpp::internal::converter( x3 )); \ END_RCPP \ } \ void RCPP_DECORATE(__NAME__)(___0, ___1, ___2, ___3) #define RPB_XP_METHOD_0(__NAME__,__CLASS__,__METHOD__ ) \ extern "C" SEXP __NAME__( SEXP xp ){ \ BEGIN_RCPP \ ::Rcpp::XPtr< __CLASS__ > ptr(xp) ; \ return ::Rcpp::wrap( ptr->__METHOD__( ) ) ; \ END_RCPP \ } #define RPB_XP_METHOD_VOID_0(__NAME__,__CLASS__,__METHOD__) \ extern "C" SEXP __NAME__( SEXP xp ){ \ BEGIN_RCPP \ ::Rcpp::XPtr< __CLASS__ > ptr(xp) ; \ ptr->__METHOD__( ) ; \ END_RCPP \ } #define RPB_XP_METHOD_CAST_0(__NAME__,__CLASS__,__METHOD__,__CAST__) \ extern "C" SEXP __NAME__( SEXP xp ){ \ BEGIN_RCPP \ ::Rcpp::XPtr< __CLASS__ > ptr(xp) ; \ return ::Rcpp::wrap( __CAST__( ptr->__METHOD__( ) ) ) ; \ END_RCPP \ } #define RPB_XP_METHOD_CAST_1(__NAME__,__CLASS__,__METHOD__,__CAST__) \ extern "C" SEXP __NAME__( SEXP xp , SEXP x0 ){ \ BEGIN_RCPP \ ::Rcpp::XPtr< __CLASS__ > ptr(xp) ; \ return ::Rcpp::wrap( __CAST__( ptr->__METHOD__( ::Rcpp::internal::converter( x0 ) ) ) ) ; \ END_RCPP \ } #endif RProtoBuf/src/ConnectionCopyingInputStream.h0000644000176200001440000000122213164671424020725 0ustar liggesusers#ifndef RPROTOBUF_ConnectionCopyingInputStream_H #define RPROTOBUF_ConnectionCopyingInputStream_H namespace rprotobuf { class ConnectionCopyingInputStream : public GPB::io::CopyingInputStream { public: ConnectionCopyingInputStream(SEXP con); int Read(void* buffer, int size); private: /* the actual connection object from R it is protected by the external pointer that wraps the ConnectionInputStream, which is the only thing that uses this class, so we don't need to take care of GC here */ SEXP con; Rcpp::Function readBin; }; } // namespace rprotobuf #endif RProtoBuf/src/wrapper_FileDescriptor.cpp0000644000176200001440000000532713164671424020124 0ustar liggesusers// -*- indent-tabs-mode: nil; tab-width: 4; show-trailing-whitespace: t; c-indent-level: 4; c-basic-offset: 4; -*- #include "rprotobuf.h" #include "RcppMacros.h" namespace rprotobuf { #undef METHOD #define METHOD(__NAME__) RCPP_PP_CAT(FileDescriptor__, __NAME__) RPB_XP_METHOD_0(METHOD(as_character), GPB::FileDescriptor, DebugString) RPB_FUNCTION_1(S4_Message, METHOD(as_Message), Rcpp::XPtr d) { GPB::FileDescriptorProto* message = new GPB::FileDescriptorProto(); d->CopyTo(message); return S4_Message(message); } RPB_FUNCTION_1(Rcpp::CharacterVector, METHOD(getMemberNames), Rcpp::XPtr desc) { int ntypes = desc->message_type_count(); int nenums = desc->enum_type_count(); int nserv = desc->service_count(); int nexts = desc->extension_count(); Rcpp::CharacterVector res(ntypes + nenums + nserv + nexts); int i = 0; int j = 0; while (i < ntypes) { res[j] = desc->message_type(i)->name(); i++; j++; } i = 0; while (i < nenums) { res[j] = desc->enum_type(i)->name(); i++; j++; } i = 0; while (i < nserv) { res[j] = desc->service(i)->name(); i++; j++; } i = 0; while (i < nexts) { res[j] = desc->extension(i)->name(); i++; j++; } return res; } /** * @param xp (GPB::FileDescriptor*) external pointer * @return the descriptor as an R list */ RPB_FUNCTION_1(Rcpp::List, METHOD(as_list), Rcpp::XPtr desc) { int ntypes = desc->message_type_count(); int nenums = desc->enum_type_count(); int nserv = desc->service_count(); int nexts = desc->extension_count(); int n = ntypes + nenums + nserv + nexts; Rcpp::CharacterVector names(n); Rcpp::List res(n); int count = 0; for (int i = 0; i < ntypes; count++, i++) { res[count] = S4_Descriptor(desc->message_type(i)); names[count] = desc->message_type(i)->name(); } for (int i = 0; i < nenums; count++, i++) { res[count] = S4_EnumDescriptor(desc->enum_type(i)); names[count] = desc->enum_type(i)->name(); } for (int i = 0; i < nserv; count++, i++) { res[count] = S4_ServiceDescriptor(desc->service(i)); names[count] = desc->service(i)->name(); } for (int i = 0; i < nexts; count++, i++) { res[count] = S4_FieldDescriptor(desc->extension(i)); // always use full names for extensions names[count] = desc->extension(i)->full_name(); } res.names() = names; return res; } RPB_FUNCTION_1(std::string, METHOD(name), Rcpp::XPtr desc) { return desc->name(); } #undef METHOD } // namespace rprotobuf RProtoBuf/src/ConnectionOutputStream.h0000644000176200001440000000055513164671424017605 0ustar liggesusers#ifndef RPROTOBUF_ConnectionOutputStream_H #define RPROTOBUF_ConnectionOutputStream_H namespace rprotobuf { class ConnectionOutputStream : public GPB::io::CopyingOutputStreamAdaptor { public: ConnectionOutputStream(SEXP con, bool was_open); ~ConnectionOutputStream(); private: bool was_open; SEXP con; }; } // namespace rprotobuf #endif RProtoBuf/src/wrapper_ArrayOutputStream.cpp0000644000176200001440000000051313164671424020651 0ustar liggesusers// -*- indent-tabs-mode: nil; tab-width: 4; show-trailing-whitespace: t; c-indent-level: 4; c-basic-offset: 4; -*- #include "rprotobuf.h" #include "RcppMacros.h" namespace rprotobuf { RPB_FUNCTION_2(S4_ArrayOutputStream, ArrayOutputStream__new, int size, int block_size) { return S4_ArrayOutputStream(size, block_size); } } RProtoBuf/src/ConnectionInputStream.h0000644000176200001440000000054713164671424017405 0ustar liggesusers#ifndef RPROTOBUF_ConnectionInputStream_H #define RPROTOBUF_ConnectionInputStream_H namespace rprotobuf { class ConnectionInputStream : public GPB::io::CopyingInputStreamAdaptor { public: ConnectionInputStream(SEXP con, bool was_open); ~ConnectionInputStream(); private: bool was_open; SEXP con; }; } // namespace rprotobuf #endif RProtoBuf/src/ZeroCopyInputStreamWrapper.cpp0000644000176200001440000000136113164671424020747 0ustar liggesusers// -*- indent-tabs-mode: nil; tab-width: 4; show-trailing-whitespace: t; c-indent-level: 4; c-basic-offset: 4; -*- #include "rprotobuf.h" namespace rprotobuf { ZeroCopyInputStreamWrapper::ZeroCopyInputStreamWrapper(GPB::io::ZeroCopyInputStream* stream) : stream(stream) { coded_stream = new GPB::io::CodedInputStream(stream); } ZeroCopyInputStreamWrapper::~ZeroCopyInputStreamWrapper() { try { /* first clear the coded stream */ delete coded_stream; /* then the stream itself */ delete stream; } catch (...) { } } GPB::io::ZeroCopyInputStream* ZeroCopyInputStreamWrapper::get_stream() { return stream; } GPB::io::CodedInputStream* ZeroCopyInputStreamWrapper::get_coded_stream() { return coded_stream; } } // namespace rprotobuf RProtoBuf/src/Makevars.in0000644000176200001440000000045413164671424015037 0ustar liggesusers## -*- mode: makefile; -*- ## Make this C++11 so that we get better int64 support and much more CXX_STD=CXX11 ## Configure tells us about locations for ## both Rcpp (ie libRcpp.so and Rcpp.h) and ## ProtoBuf headers and library via these variables PKG_CPPFLAGS=@PKG_CPPFLAGS@ PKG_LIBS=@PKG_LIBS@ RProtoBuf/src/ConnectionInputStream.cpp0000644000176200001440000000164413164671424017737 0ustar liggesusers// -*- indent-tabs-mode: nil; tab-width: 4; show-trailing-whitespace: t; c-indent-level: 4; c-basic-offset: 4; -*- #include "rprotobuf.h" #include "ConnectionInputStream.h" #include "ConnectionCopyingInputStream.h" namespace rprotobuf { ConnectionInputStream::ConnectionInputStream(SEXP con, bool was_open) : GPB::io::CopyingInputStreamAdaptor(new ConnectionCopyingInputStream(con)), was_open(was_open), con(con) { /* clean the wrapped stream on delete */ SetOwnsCopyingStream(true); } ConnectionInputStream::~ConnectionInputStream() { if (!was_open) { /* then we need to close it */ SEXP call = PROTECT(Rf_lang2(Rf_install("close"), con)); Rf_eval(call, R_GlobalEnv); UNPROTECT(1); /* call */ } /* con will be disposed by the R GC, it is protected as part of the protection of the external pointer that wraps this */ } } // namespace rprotobuf RProtoBuf/src/ConnectionOutputStream.cpp0000644000176200001440000000172113164671424020134 0ustar liggesusers// -*- indent-tabs-mode: nil; tab-width: 4; show-trailing-whitespace: t; c-indent-level: 4; c-basic-offset: 4; -*- #include "rprotobuf.h" #include "ConnectionOutputStream.h" #include "ConnectionCopyingOutputStream.h" namespace rprotobuf { ConnectionOutputStream::ConnectionOutputStream(SEXP con, bool was_open) : GPB::io::CopyingOutputStreamAdaptor(new ConnectionCopyingOutputStream(con)), was_open(was_open), con(con) { /* clean the wrapped stream on delete */ SetOwnsCopyingStream(true); } ConnectionOutputStream::~ConnectionOutputStream() { if (!was_open) { /* then we need to close it */ SEXP call = PROTECT(Rf_lang2(Rf_install("close"), con)); (void)Rf_eval(call, R_GlobalEnv); // Ignore SEXP return val of close(). UNPROTECT(1); /* call */ } /* con will be disposed by the R GC, it is protected as part of the protection of the external pointer that wraps this */ } } // namespace rprotobuf RProtoBuf/src/RWarningErrorCollector.h0000644000176200001440000000060413164671424017514 0ustar liggesusers#include /* For string */ #include "rprotobuf.h" namespace rprotobuf { class RWarningErrorCollector : public GPB::compiler::MultiFileErrorCollector { public: // implements ErrorCollector --------------------------------------- void AddError(const std::string& filename, int line, int column, const std::string& message); }; } // namespace rprotobuf RProtoBuf/src/wrapper_Message.cpp0000644000176200001440000011462213164671424016571 0ustar liggesusers// -*- indent-tabs-mode: nil; tab-width: 4; show-trailing-whitespace: t; c-indent-level: 4; c-basic-offset: 4; -*- #include "rprotobuf.h" #include "fieldtypes.h" #include "RcppMacros.h" #define SAME(x, y, tol) ((tol == 0.0 && x == y) || (((x - y) * (x - y) < tol* tol) ? 1 : 0)) namespace rprotobuf { /* helpers */ /* this is only to be called for repeated fields */ int MESSAGE_GET_REPEATED_INT(const GPB::Message* message, const GPB::FieldDescriptor* field_desc, int index) { const GPB::Reflection* ref = message->GetReflection(); switch (field_desc->type()) { case TYPE_INT32: case TYPE_SINT32: case TYPE_SFIXED32: return (int)ref->GetRepeatedInt32(*message, field_desc, index); case TYPE_INT64: case TYPE_SINT64: case TYPE_SFIXED64: return (int)ref->GetRepeatedInt64(*message, field_desc, index); case TYPE_UINT32: case TYPE_FIXED32: return (int)ref->GetRepeatedUInt32(*message, field_desc, index); case TYPE_UINT64: case TYPE_FIXED64: return (int)ref->GetRepeatedUInt64(*message, field_desc, index); case TYPE_ENUM: return ref->GetRepeatedEnum(*message, field_desc, index)->number(); default: Rcpp_error("cannot cast to int"); } return 0; // Unreachable for -Wall } /* this is only to be called for repeated fields */ double MESSAGE_GET_REPEATED_DOUBLE(const GPB::Message* message, const GPB::FieldDescriptor* field_desc, int index) { const GPB::Reflection* ref = message->GetReflection(); switch (field_desc->type()) { case TYPE_FLOAT: return (double)ref->GetRepeatedFloat(*message, field_desc, index); case TYPE_DOUBLE: return (double)ref->GetRepeatedDouble(*message, field_desc, index); default: Rcpp_error("cannot cast to double"); } return 0; // -Wall } #undef METHOD #define METHOD(__NAME__) RCPP_PP_CAT(Message__, __NAME__) /** * Clone a message * * @param xp external pointer to a message * @return a new message, clone of the input message */ RPB_FUNCTION_1(S4_Message, METHOD(clone), Rcpp::XPtr message) { /* cloning message as sheep */ GPB::Message* sheep = message->New(); sheep->CopyFrom(*message); return S4_Message(sheep); } /** * TRUE if the message has the specified field name. * FALSE otherwise. * * * @param xp external pointer to the Message * @param name name of the field */ RPB_FUNCTION_2(bool, METHOD(field_exists), Rcpp::XPtr message, std::string name) { const GPB::Descriptor* desc = message->GetDescriptor(); const GPB::FieldDescriptor* field_desc = desc->FindFieldByName(name); return (field_desc != NULL); } /** * TRUE if the message has the field name and it is populated. * FALSE otherwise. * * @param xp external pointer to the Message * @param name name of the field */ RPB_FUNCTION_2(bool, METHOD(has_field), Rcpp::XPtr message, std::string name) { const GPB::Descriptor* desc = message->GetDescriptor(); const GPB::FieldDescriptor* field_desc = desc->FindFieldByName(name); bool res = false; if (field_desc) { const GPB::Reflection* ref = message->GetReflection(); if (field_desc->is_repeated()) { res = ref->FieldSize(*message, field_desc) > 0; } else { res = ref->HasField(*message, field_desc); } } return res; } /** * Check if all required fields are set * * @param xp external pointer to the Message */ RPB_FUNCTION_1(bool, METHOD(is_initialized), Rcpp::XPtr message) { return message->IsInitialized(); } /** * Serialize a message to a file * * @param xp external pointer to a GPB::Message* * @param filename file name where to serialize */ RPB_FUNCTION_VOID_2(METHOD(serialize_to_file), Rcpp::XPtr message, const char* filename) { /* open the file in binary mode to write */ /* we make sure in the R side that filename is the full path of the file */ int file = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666); /* using partial to allow partially filled messages */ // TODO(mstokely): Check return value and throw Rcpp::stop if 0? message->SerializePartialToFileDescriptor(file); close(file); } /** * Create a raw vector that contains the content of the serialized message * * @param xp xternal pointer to the message */ RPB_FUNCTION_1(Rcpp::RawVector, METHOD(get_payload), Rcpp::XPtr message) { /* create a raw vector of the appropriate size */ int size = message->ByteSize(); Rcpp::RawVector payload(size); /* fill the array */ message->SerializePartialToArray(payload.begin(), size); return (payload); } RPB_XP_METHOD_VOID_0(METHOD(clear), GPB::Message, Clear) /** * Clear a field of a message * * @param xp (GPB::Message*) external pointer * @param field name or tag of the field */ RPB_FUNCTION_VOID_2(METHOD(clear_field), Rcpp::XPtr m, SEXP field) { const GPB::FieldDescriptor* field_desc = getFieldDescriptor(m, field); const GPB::Reflection* ref = m->GetReflection(); ref->ClearField(m, field_desc); } /** * Return a named list representation of the fields set in a message. * * @param xp external pointer to a Message * @return the message as an R list */ RPB_FUNCTION_1(Rcpp::List, METHOD(as_list), Rcpp::XPtr message) { const GPB::Descriptor* desc = message->GetDescriptor(); int nf = desc->field_count(); Rcpp::CharacterVector fieldNames(nf); Rcpp::List val(nf); /* TODO: not use getMessageField */ for (int i = 0; i < nf; i++) { const GPB::FieldDescriptor* fd = desc->field(i); val[i] = getMessageField(message, Rcpp::CharacterVector::create(fd->name())); fieldNames[i] = fd->name(); } val.names() = fieldNames; return val; } /** * The number of fields the message has. A field counts in these two situations: * - it is repeated and the array size is greater than 0 * - it is not repeated and the message has it * * @param xp external pointer to the Message */ RPB_FUNCTION_1(int, METHOD(length), Rcpp::XPtr message) { const GPB::Descriptor* desc = message->GetDescriptor(); const GPB::Reflection* ref = message->GetReflection(); int nfields = desc->field_count(); int res = 0; for (int i = 0; i < nfields; i++) { const GPB::FieldDescriptor* field_desc = desc->field(i); if (field_desc->is_repeated()) { if (ref->FieldSize(*message, field_desc) > 0) { res++; } } else { if (ref->HasField(*message, field_desc)) { res++; } } } return res; } /** * The number of extensions the message has. * * @param xp external pointer to the Message */ RPB_FUNCTION_1(int, METHOD(num_extensions), Rcpp::XPtr message) { const GPB::Reflection* ref = message->GetReflection(); int nexts = 0; vector fields; ref->ListFields(*message, &fields); for (unsigned int i = 0; i < fields.size(); i++) { if (fields[i]->is_extension()) { nexts++; } } return nexts; } /** * Get the message descriptor of a Message. * * @param xp (GPB::Message*) external pointer * @return the descriptor, as a Descriptor R S4 object */ RPB_FUNCTION_1(S4_Descriptor, METHOD(descriptor), Rcpp::XPtr message) { return (message->GetDescriptor()); } RPB_XP_METHOD_0(METHOD(as_character), GPB::Message, DebugString) RPB_XP_METHOD_0(METHOD(bytesize), GPB::Message, ByteSize) RPB_FUNCTION_2(int, METHOD(field_size), Rcpp::XPtr message, SEXP field) { const GPB::FieldDescriptor* field_desc = getFieldDescriptor(message, field); int res = 0; if (field_desc->is_repeated()) { res = message->GetReflection()->FieldSize(*message, field_desc); } else { res = message->GetReflection()->HasField(*message, field_desc) ? 1 : 0; } return res; } RPB_FUNCTION_1(S4_FileDescriptor, METHOD(fileDescriptor), Rcpp::XPtr message) { return S4_FileDescriptor(message->GetDescriptor()->file()); } RPB_FUNCTION_VOID_3(METHOD(set_field_size), Rcpp::XPtr message, SEXP field, int target) { const GPB::FieldDescriptor* field_desc = getFieldDescriptor(message, field); const GPB::Reflection* ref = message->GetReflection(); if (field_desc->is_repeated()) { int current = ref->FieldSize(*message, field_desc); if (target == 0) { ref->ClearField(message, field_desc); } else if (current > target) { while (current != target) { ref->RemoveLast(message, field_desc); current--; } } else if (current == target) { /* nothing to do */ } else {/* current < target */ while (current != target) { switch (field_desc->type()) { case TYPE_INT32: case TYPE_SINT32: case TYPE_SFIXED32: { ref->AddInt32(message, field_desc, (int32)0); break; } case TYPE_INT64: case TYPE_SINT64: case TYPE_SFIXED64: { ref->AddInt64(message, field_desc, (int64)0); break; } case TYPE_UINT32: case TYPE_FIXED32: { ref->AddUInt32(message, field_desc, (uint32)0); break; } case TYPE_UINT64: case TYPE_FIXED64: { ref->AddUInt32(message, field_desc, (uint64)0); break; } case TYPE_DOUBLE: { ref->AddDouble(message, field_desc, (double)0.0); break; } case TYPE_FLOAT: { ref->AddFloat(message, field_desc, (float)0.0); break; } case TYPE_BOOL: { ref->AddBool(message, field_desc, (bool)0); break; } case TYPE_STRING: case TYPE_BYTES: { ref->AddString(message, field_desc, ""); break; } case TYPE_MESSAGE: case TYPE_GROUP: { /* fill with the prototype for that message type */ Rcpp_error("growing repeated messages not implemented, patches welcome"); break; } case TYPE_ENUM: { /* fill with the prototype for that message type */ Rcpp_error("growing repeated enums not implemented yet, patches welcome"); break; } } /* switch */ current++; } /* while */ } } else { if (target == 0) { if (ref->HasField(*message, field_desc)) { ref->ClearField(message, field_desc); } } else { if (!ref->HasField(*message, field_desc)) { switch (field_desc->type()) { case TYPE_INT32: case TYPE_SINT32: case TYPE_SFIXED32: { ref->SetInt32(message, field_desc, (int32)0); break; } case TYPE_INT64: case TYPE_SINT64: case TYPE_SFIXED64: { ref->SetInt64(message, field_desc, (int64)0); break; } case TYPE_UINT32: case TYPE_FIXED32: { ref->SetUInt32(message, field_desc, (uint32)0); break; } case TYPE_UINT64: case TYPE_FIXED64: { ref->SetUInt32(message, field_desc, (uint64)0); break; } case TYPE_DOUBLE: { ref->SetDouble(message, field_desc, (double)0.0); break; } case TYPE_FLOAT: { ref->SetFloat(message, field_desc, (float)0.0); break; } case TYPE_BOOL: { ref->SetBool(message, field_desc, (bool)0); break; } case TYPE_STRING: case TYPE_BYTES: { ref->SetString(message, field_desc, ""); break; } case TYPE_MESSAGE: case TYPE_GROUP: { /* fill with the prototype for that message type */ Rcpp_error("not implemented yet, patches welcome"); break; } case TYPE_ENUM: { /* fill with the prototype for that message type */ Rcpp_error("not implemented yet, patches welcome"); break; } } } } } } /** * Returns the field names of the message. * * @param xp external pointer to a Message * * @return field names, as an R character vector (STRSXP) */ RPB_FUNCTION_1(Rcpp::CharacterVector, METHOD(fieldNames), Rcpp::XPtr message) { const GPB::Descriptor* desc = message->GetDescriptor(); int nfields = desc->field_count(); Rcpp::CharacterVector res(nfields); for (int i = 0; i < nfields; i++) { res[i] = desc->field(i)->name(); } return (res); } bool identical_messages_(const GPB::Message* m1, const GPB::Message* m2, double tol) { const GPB::Descriptor* d1 = m1->GetDescriptor(); const GPB::Descriptor* d2 = m2->GetDescriptor(); /* first of all, check if this is the same message type */ if (d1 != d2) { return false; } const GPB::Reflection* ref = m2->GetReflection(); /* iterate field descriptors */ int nf = d1->field_count(); for (int i = 0; i < nf; i++) { const GPB::FieldDescriptor* field_desc = d1->field(i); if (field_desc->is_repeated()) { /* test if the size differs */ int fs = ref->FieldSize(*m1, field_desc); if (fs != ref->FieldSize(*m2, field_desc)) return false; /* test all items */ switch (field_desc->type()) { case TYPE_INT32: case TYPE_SINT32: case TYPE_SFIXED32: { for (int j = 0; j < fs; j++) { if (ref->GetRepeatedInt32(*m1, field_desc, j) != ref->GetRepeatedInt32(*m2, field_desc, j)) return false; } break; } case TYPE_INT64: case TYPE_SINT64: case TYPE_SFIXED64: { for (int j = 0; j < fs; j++) { if (ref->GetRepeatedInt64(*m1, field_desc, j) != ref->GetRepeatedInt64(*m2, field_desc, j)) return false; } break; } case TYPE_UINT32: case TYPE_FIXED32: { for (int j = 0; j < fs; j++) { if (ref->GetRepeatedUInt32(*m1, field_desc, j) != ref->GetRepeatedUInt32(*m2, field_desc, j)) return false; } break; } case TYPE_UINT64: case TYPE_FIXED64: { for (int j = 0; j < fs; j++) { if (ref->GetRepeatedUInt64(*m1, field_desc, j) != ref->GetRepeatedUInt64(*m2, field_desc, j)) return false; } break; } case TYPE_DOUBLE: { for (int j = 0; j < fs; j++) { if (!SAME(ref->GetRepeatedDouble(*m1, field_desc, j), ref->GetRepeatedDouble(*m2, field_desc, j), tol)) return false; } break; } case TYPE_FLOAT: { for (int j = 0; j < fs; j++) { if (!SAME(ref->GetRepeatedFloat(*m1, field_desc, j), ref->GetRepeatedFloat(*m2, field_desc, j), tol)) return false; } break; } case TYPE_BOOL: { for (int j = 0; j < fs; j++) { if (ref->GetRepeatedBool(*m1, field_desc, j) != ref->GetRepeatedBool(*m2, field_desc, j)) return false; } break; } case TYPE_STRING: case TYPE_BYTES: { for (int j = 0; j < fs; j++) { if (ref->GetRepeatedString(*m1, field_desc, j) != ref->GetRepeatedString(*m2, field_desc, j)) return false; } break; } case TYPE_ENUM: { for (int j = 0; j < fs; j++) { if (ref->GetRepeatedEnum(*m1, field_desc, j) != ref->GetRepeatedEnum(*m2, field_desc, j)) return false; } break; } case TYPE_MESSAGE: case TYPE_GROUP: { for (int j = 0; j < fs; j++) { const GPB::Message* mm1 = &ref->GetRepeatedMessage(*m1, field_desc, j); const GPB::Message* mm2 = &ref->GetRepeatedMessage(*m2, field_desc, j); if (!identical_messages_(mm1, mm2, tol)) { return false; } } break; } default: Rcpp_error("unknown type"); } } else { switch (field_desc->type()) { case TYPE_INT32: case TYPE_SINT32: case TYPE_SFIXED32: { if (ref->GetInt32(*m1, field_desc) != ref->GetInt32(*m2, field_desc)) return false; break; } case TYPE_INT64: case TYPE_SINT64: case TYPE_SFIXED64: { if (ref->GetInt64(*m1, field_desc) != ref->GetInt64(*m2, field_desc)) return false; break; } case TYPE_UINT32: case TYPE_FIXED32: { if (ref->GetUInt32(*m1, field_desc) != ref->GetUInt32(*m2, field_desc)) return false; break; } case TYPE_UINT64: case TYPE_FIXED64: { if (ref->GetUInt64(*m1, field_desc) != ref->GetUInt64(*m2, field_desc)) return false; break; } case TYPE_DOUBLE: { if (ref->GetDouble(*m1, field_desc) != ref->GetDouble(*m2, field_desc)) return false; break; } case TYPE_FLOAT: { if (ref->GetFloat(*m1, field_desc) != ref->GetFloat(*m2, field_desc)) return false; break; } case TYPE_BOOL: { if (ref->GetBool(*m1, field_desc) != ref->GetBool(*m2, field_desc)) return false; break; } case TYPE_STRING: case TYPE_BYTES: { if (ref->GetString(*m1, field_desc) != ref->GetString(*m2, field_desc)) return false; break; } case TYPE_ENUM: { if (ref->GetEnum(*m1, field_desc) != ref->GetEnum(*m2, field_desc)) return false; break; } case TYPE_MESSAGE: case TYPE_GROUP: { const GPB::Message* mm1 = &ref->GetMessage(*m1, field_desc); const GPB::Message* mm2 = &ref->GetMessage(*m2, field_desc); if (!identical_messages_(mm1, mm2, tol)) { return false; } break; } default: Rcpp_error("unknown type"); } } } /* finally */ return true; } RPB_FUNCTION_2(bool, identical_messages, Rcpp::XPtr m1, Rcpp::XPtr m2) { return identical_messages_(m1, m2, 0.0); } RPB_FUNCTION_3(bool, all_equal_messages, Rcpp::XPtr m1, Rcpp::XPtr m2, double tol) { return identical_messages_(m1, m2, tol); } RPB_FUNCTION_VOID_4(METHOD(swap), Rcpp::XPtr message, SEXP field, Rcpp::IntegerVector left, Rcpp::IntegerVector right) { GPB::FieldDescriptor* field_desc = getFieldDescriptor(message, field); const GPB::Reflection* ref = message->GetReflection(); if (!field_desc->is_repeated()) { throw std::range_error("swap can only be used with repeated fields"); } int n = LENGTH(left); /* we know that length(left) == length(right) */ for (int i = 0; i < n; i++) { ref->SwapElements(message, field_desc, left[i], right[i]); } } /** * Creates a new message by merging two messages of the same type. * * @param xp1 external pointer to a GPB::Message* * @param xp2 external pointer to a GPB::Message* * * @return a new message, as an R object of "Message" S4 class */ RPB_FUNCTION_2(S4_Message, METHOD(merge), Rcpp::XPtr m1, Rcpp::XPtr m2) { GPB::Message* merged = m1->New(); merged->MergeFrom(*m1); merged->MergeFrom(*m2); return S4_Message(merged); } /** * Add values to a repeated field. * * @param xp (GPB::Message*) external pointer * @param field field tag number or name * @param values values to append */ RPB_FUNCTION_VOID_3(METHOD(add_values), Rcpp::XPtr message, SEXP field, SEXP values) { const Reflection* ref = message->GetReflection(); const GPB::FieldDescriptor* field_desc = getFieldDescriptor(message, field); if (values == R_NilValue || LENGTH(values) == 0) { return; } if (field_desc->is_repeated()) { /* first check */ switch (field_desc->type()) { case TYPE_ENUM: { CHECK_values_for_enum(field_desc, values); break; } case TYPE_MESSAGE: case TYPE_GROUP: { CHECK_messages(field_desc, values); break; } default: { // nothing } } int value_size = LENGTH(values); /* then add the values */ switch (field_desc->type()) { // {{{ int32 case TYPE_INT32: case TYPE_SINT32: case TYPE_SFIXED32: { switch (TYPEOF(values)) { case INTSXP: case REALSXP: case LGLSXP: case RAWSXP: { for (int i = 0; i < value_size; i++) { ref->AddInt32(message, field_desc, GET_int32(values, i)); } break; } default: Rcpp::stop("Cannot convert to int32"); } break; } // }}} // {{{ int64 case TYPE_INT64: case TYPE_SINT64: case TYPE_SFIXED64: { switch (TYPEOF(values)) { case INTSXP: case REALSXP: case LGLSXP: case RAWSXP: for (int i = 0; i < value_size; i++) { ref->AddInt64(message, field_desc, GET_int64(values, i)); } break; default: Rcpp::stop("Cannot convert to int64"); } break; } // }}} // {{{ uint32 case TYPE_UINT32: case TYPE_FIXED32: { switch (TYPEOF(values)) { case INTSXP: case REALSXP: case LGLSXP: case RAWSXP: { for (int i = 0; i < value_size; i++) { ref->AddUInt32(message, field_desc, GET_uint32(values, i)); } break; } default: Rcpp::stop("Cannot convert to uint32"); } break; } // }}} // {{{ uint64 case TYPE_UINT64: case TYPE_FIXED64: { switch (TYPEOF(values)) { case INTSXP: case REALSXP: case LGLSXP: case RAWSXP: { for (int i = 0; i < value_size; i++) { ref->AddUInt64(message, field_desc, GET_uint64(values, i)); } break; } default: Rcpp::stop("Cannot convert to int64"); } break; } // }}} // {{{ double case TYPE_DOUBLE: { switch (TYPEOF(values)) { case INTSXP: case REALSXP: case LGLSXP: case RAWSXP: { for (int i = 0; i < value_size; i++) { ref->AddDouble(message, field_desc, GET_double(values, i)); } break; } default: Rcpp::stop("Cannot convert to double"); } break; } // }}} // {{{ float case TYPE_FLOAT: { switch (TYPEOF(values)) { case INTSXP: case REALSXP: case LGLSXP: case RAWSXP: { for (int i = 0; i < value_size; i++) { ref->AddFloat(message, field_desc, GET_float(values, i)); } break; } default: Rcpp::stop("Cannot convert to float"); } break; } // }}} // {{{ bool case TYPE_BOOL: { switch (TYPEOF(values)) { case INTSXP: case REALSXP: case LGLSXP: case RAWSXP: { for (int i = 0; i < value_size; i++) { ref->AddBool(message, field_desc, GET_bool(values, i)); } break; } default: Rcpp::stop("Cannot convert to bool"); } break; } // }}} // {{{ string case TYPE_STRING: { if (TYPEOF(values) == STRSXP) { for (int i = 0; i < value_size; i++) { ref->AddString(message, field_desc, COPYSTRING(CHAR(STRING_ELT(values, i)))); } } else { Rcpp::stop("Cannot convert to string"); } break; } // }}} // {{{ bytes case TYPE_BYTES: { if (TYPEOF(values) == RAWSXP) { ref->AddString(message, field_desc, GET_bytes(values, 0)); } else if (TYPEOF(values) == VECSXP) { for (int i = 0; i < value_size; i++) { ref->AddString(message, field_desc, GET_bytes(values, i)); } } else { Rcpp::stop("Cannot convert to bytes"); } break; } // }}} // {{{ message case TYPE_MESSAGE: case TYPE_GROUP: { if (TYPEOF(values) == VECSXP) { for (int i = 0; i < value_size; i++) { GPB::Message* mess = GET_MESSAGE_POINTER_FROM_S4(VECTOR_ELT(values, i)); /* we already know it is of the correct type because of premptive check above */ ref->AddMessage(message, field_desc)->CopyFrom(*mess); } } else { Rcpp::stop("type mismatch, expecting a list of 'Message' objects"); } break; } // }}} // {{{ enum case TYPE_ENUM: { const GPB::EnumDescriptor* enum_desc = field_desc->enum_type(); switch (TYPEOF(values)) { // {{{ numbers case INTSXP: case REALSXP: case LGLSXP: case RAWSXP: { for (int i = 0; i < value_size; i++) { int val = GET_int(values, i); ref->AddEnum(message, field_desc, enum_desc->FindValueByNumber(val)); } break; } // }}} // {{{ STRSXP case STRSXP: { for (int i = 0; i < value_size; i++) { std::string val = CHAR(STRING_ELT(values, i)); const GPB::EnumValueDescriptor* evd = enum_desc->FindValueByName(val); ref->AddEnum(message, field_desc, evd); } break; } // }}} default: Rcpp::stop("cannot set enum value"); } break; } // }}} default: { // nothing } } } else { Rcpp::stop("add can only be used on repeated fields"); } } /** * Fetch a subset of the values of a field. * * @param (GPB::Message*) external pointer * @param field name or tag number of the field * @param index */ RPB_FUNCTION_3(SEXP, METHOD(get_field_values), Rcpp::XPtr message, SEXP field, Rcpp::IntegerVector index) { GPB::FieldDescriptor* field_desc = getFieldDescriptor(message, field); if (!field_desc->is_repeated()) { Rcpp_error("fetch can only be used on repeated fields"); } int n = index.size(); switch (field_desc->type()) { case TYPE_INT32: case TYPE_SINT32: case TYPE_SFIXED32: case TYPE_INT64: case TYPE_SINT64: case TYPE_SFIXED64: case TYPE_UINT32: case TYPE_FIXED32: case TYPE_UINT64: case TYPE_FIXED64: case TYPE_ENUM: { Rcpp::IntegerVector res(n); for (int i = 0; i < n; i++) { res[i] = MESSAGE_GET_REPEATED_INT(message, field_desc, index[i]); } return res; } case TYPE_DOUBLE: case TYPE_FLOAT: { Rcpp::NumericVector res(n); for (int i = 0; i < n; i++) { res[i] = MESSAGE_GET_REPEATED_DOUBLE(message, field_desc, index[i]); } return res; } case TYPE_BOOL: { Rcpp::LogicalVector res(n); for (int i = 0; i < n; i++) { res[i] = MESSAGE_GET_REPEATED_DOUBLE(message, field_desc, index[i]); } return res; } case TYPE_STRING: { const GPB::Reflection* ref = message->GetReflection(); Rcpp::CharacterVector res(n); for (int i = 0; i < n; i++) { res[i] = ref->GetRepeatedString(*message, field_desc, index[i]); } return res; } case TYPE_BYTES: { const GPB::Reflection* ref = message->GetReflection(); Rcpp::List res(n); for (int i = 0; i < n; i++) { std::string s = ref->GetRepeatedString(*message, field_desc, index[i]); res[i] = std::vector(s.begin(), s.end()); } return res; } case TYPE_MESSAGE: case TYPE_GROUP: { const GPB::Reflection* ref = message->GetReflection(); Rcpp::List res(n); for (int i = 0; i < n; i++) { res[i] = S4_Message(CLONE(&ref->GetRepeatedMessage(*message, field_desc, i))); } return res; } default: throw std::range_error("unknown type"); } return R_NilValue; // Unreachable. For -Wall } /** * set the values of a repeated field * * @param xp (GPB::Message*) external pointer * @param field field tag number or name * @param index positions (0-based) * @param values new values */ RPB_FUNCTION_VOID_4(METHOD(set_field_values), Rcpp::XPtr message, SEXP field, Rcpp::IntegerVector index, SEXP values) { const GPB::FieldDescriptor* field_desc = getFieldDescriptor(message, field); if (!field_desc->is_repeated()) { throw std::range_error("set can only be used on repeated fields"); } const GPB::Reflection* ref = message->GetReflection(); /* we know here that LENGTH(index) == LENGTH(values) */ int n = index.size(); switch (field_desc->type()) { case TYPE_INT32: case TYPE_SINT32: case TYPE_SFIXED32: { for (int i = 0; i < n; i++) { ref->SetRepeatedInt32(message, field_desc, index[i], GET_int32(values, i)); } break; } case TYPE_INT64: case TYPE_SINT64: case TYPE_SFIXED64: { for (int i = 0; i < n; i++) { ref->SetRepeatedInt64(message, field_desc, index[i], GET_int64(values, i)); } break; } case TYPE_UINT32: case TYPE_FIXED32: { for (int i = 0; i < n; i++) { ref->SetRepeatedUInt32(message, field_desc, GET_int(index, i), GET_uint32(values, i)); } break; } case TYPE_UINT64: case TYPE_FIXED64: { for (int i = 0; i < n; i++) { ref->SetRepeatedUInt64(message, field_desc, index[i], GET_uint64(values, i)); } break; } case TYPE_DOUBLE: { for (int i = 0; i < n; i++) { ref->SetRepeatedDouble(message, field_desc, index[i], GET_double(values, i)); } break; } case TYPE_FLOAT: { for (int i = 0; i < n; i++) { ref->SetRepeatedFloat(message, field_desc, index[i], GET_float(values, i)); } break; } case TYPE_BOOL: { for (int i = 0; i < n; i++) { ref->SetRepeatedBool(message, field_desc, index[i], GET_bool(values, i)); } break; } case TYPE_STRING: { for (int i = 0; i < n; i++) { ref->SetRepeatedString(message, field_desc, index[i], GET_stdstring(values, i)); } break; } case TYPE_BYTES: { for (int i = 0; i < n; i++) { ref->SetRepeatedString(message, field_desc, index[i], GET_bytes(values, i)); } break; } case TYPE_ENUM: { CHECK_values_for_enum(field_desc, values); const GPB::EnumDescriptor* enum_desc = field_desc->enum_type(); switch (TYPEOF(values)) { case INTSXP: case REALSXP: case LGLSXP: case RAWSXP: { for (int i = 0; i < n; i++) { int val = GET_int(values, i); ref->SetRepeatedEnum(message, field_desc, i, enum_desc->FindValueByNumber(val)); } break; } case STRSXP: { Rcpp::CharacterVector vals(values); std::string val; for (int i = 0; i < n; i++) { val = vals[i]; const GPB::EnumValueDescriptor* evd = enum_desc->FindValueByName(val); ref->SetRepeatedEnum(message, field_desc, i, evd); } break; } default: throw std::range_error("impossible to convert to a enum"); } break; } case TYPE_MESSAGE: case TYPE_GROUP: { CHECK_messages(field_desc, values); Rcpp::List vals(values); for (int i = 0; i < n; i++) { GPB::Message* mess = GET_MESSAGE_POINTER_FROM_S4(vals[i]); ref->MutableRepeatedMessage(message, field_desc, i)->CopyFrom(*mess); } break; } default: throw std::range_error("unknown type"); } } #undef METHOD } RProtoBuf/src/wrapper_ArrayInputStream.cpp0000644000176200001440000000055113164671424020452 0ustar liggesusers// -*- indent-tabs-mode: nil; tab-width: 4; show-trailing-whitespace: t; c-indent-level: 4; c-basic-offset: 4; -*- #include "rprotobuf.h" #include "RcppMacros.h" namespace rprotobuf { RPB_FUNCTION_2(S4_ArrayInputStream, ArrayInputStream__new, Rcpp::RawVector payload, int block_size) { return S4_ArrayInputStream(payload, block_size); } } RProtoBuf/src/Makevars.win0000644000176200001440000000066213164671424015227 0ustar liggesusers# Links against libprotobuf build from Rtools gcc toolchain. COMPILED_BY ?= gcc-4.6.3 PKG_CPPFLAGS= -I../windows/protobuf-3.0.0/include PKG_LIBS= -L../windows/protobuf-3.0.0/lib${subst gcc,,${COMPILED_BY}}${R_ARCH} -lprotobuf ## Make this C++11 so that we get better int64 support and more CXX_STD=CXX11 all: clean winlibs clean: rm -f $(OBJECTS) $(SHLIB) winlibs: "${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" "../tools/winlibs.R" RProtoBuf/src/init.c0000644000176200001440000006024513164671424014051 0ustar liggesusers#include #include #include // for NULL #include /* The following name(s) appear with different usages e.g., with different numbers of arguments: Message__clone This needs to be resolved in the tables and any declarations. DE 2017-03-05: Resolved, second entry with two arguments was in error */ /* DE 2017-03-05: - Below several entries were commented out as unresolvable - A few were renamed with suffix _cpp to avoid name clash with R symbols of the same name as we also enable .registration=TRUE in useDynLib in NAMESPACE */ /* FIXME: Check these declarations against the C/Fortran source code. */ /* .Call calls */ extern SEXP all_equal_messages(SEXP, SEXP, SEXP); extern SEXP ArrayInputStream__new(SEXP, SEXP); extern SEXP ArrayOutputStream__new(SEXP, SEXP); extern SEXP ConnectionInputStream_new(SEXP, SEXP); extern SEXP ConnectionOutputStream_new(SEXP, SEXP); extern SEXP Descriptor__as_character(SEXP); extern SEXP Descriptor__as_list(SEXP); extern SEXP Descriptor__as_Message(SEXP); extern SEXP Descriptor__containing_type(SEXP); extern SEXP Descriptor__enum_type(SEXP, SEXP); extern SEXP Descriptor__enum_type_count(SEXP); extern SEXP Descriptor__field(SEXP, SEXP); extern SEXP Descriptor__field_count(SEXP); extern SEXP Descriptor__fileDescriptor(SEXP); /*extern SEXP Descriptor__FindEnumTypeByName(SEXP, SEXP);*/ extern SEXP Descriptor__FindFieldByName(SEXP, SEXP); extern SEXP Descriptor__FindFieldByNumber(SEXP, SEXP); extern SEXP Descriptor__FindNestedTypeByName(SEXP, SEXP); extern SEXP Descriptor__getMemberNames(SEXP); extern SEXP Descriptor__name(SEXP, SEXP); extern SEXP Descriptor__nested_type(SEXP, SEXP); extern SEXP Descriptor__nested_type_count(SEXP); extern SEXP Descriptor__readASCIIFromConnection(SEXP, SEXP, SEXP); extern SEXP Descriptor__readASCIIFromString(SEXP, SEXP, SEXP); extern SEXP Descriptor__readMessageFromConnection(SEXP, SEXP); extern SEXP Descriptor__readMessageFromFile(SEXP, SEXP); extern SEXP Descriptor__readMessageFromRawVector(SEXP, SEXP); extern SEXP Descriptor_getField(SEXP, SEXP); extern SEXP do_dollar_Descriptor(SEXP, SEXP); extern SEXP EnumDescriptor__as_character(SEXP); extern SEXP EnumDescriptor__as_list(SEXP); extern SEXP EnumDescriptor__as_Message(SEXP); extern SEXP EnumDescriptor__containing_type(SEXP); extern SEXP EnumDescriptor__fileDescriptor(SEXP); extern SEXP EnumDescriptor__getConstantNames(SEXP); extern SEXP EnumDescriptor__getValueByIndex(SEXP, SEXP); extern SEXP EnumDescriptor__getValueByName(SEXP, SEXP); extern SEXP EnumDescriptor__getValueByNumber(SEXP, SEXP); extern SEXP EnumDescriptor__length(SEXP); extern SEXP EnumDescriptor__name(SEXP, SEXP); extern SEXP EnumDescriptor__value_count(SEXP); extern SEXP EnumValueDescriptor__as_character(SEXP); extern SEXP EnumValueDescriptor__as_Message(SEXP); extern SEXP EnumValueDescriptor__enum_type(SEXP); extern SEXP EnumValueDescriptor__number(SEXP); extern SEXP FieldDescriptor__as_character(SEXP); extern SEXP FieldDescriptor__as_Message(SEXP); extern SEXP FieldDescriptor__containing_type(SEXP); extern SEXP FieldDescriptor__cpp_type(SEXP); extern SEXP FieldDescriptor__default_value(SEXP); extern SEXP FieldDescriptor__enum_type(SEXP); extern SEXP FieldDescriptor__fileDescriptor(SEXP); extern SEXP FieldDescriptor__has_default_value(SEXP); extern SEXP FieldDescriptor__is_extension(SEXP); extern SEXP FieldDescriptor__is_optional(SEXP); extern SEXP FieldDescriptor__is_repeated(SEXP); extern SEXP FieldDescriptor__is_required(SEXP); extern SEXP FieldDescriptor__label(SEXP); extern SEXP FieldDescriptor__message_type(SEXP); extern SEXP FieldDescriptor__name(SEXP, SEXP); extern SEXP FieldDescriptor__number(SEXP); extern SEXP FieldDescriptor__type(SEXP); extern SEXP FileDescriptor__as_character(SEXP); extern SEXP FileDescriptor__as_list(SEXP); extern SEXP FileDescriptor__as_Message(SEXP); extern SEXP FileDescriptor__getMemberNames(SEXP); extern SEXP FileDescriptor__name(SEXP); extern SEXP FileInputStream_Close(SEXP); extern SEXP FileInputStream_GetErrno(SEXP); extern SEXP FileInputStream_new(SEXP, SEXP, SEXP); extern SEXP FileInputStream_SetCloseOnDelete(SEXP, SEXP); extern SEXP FileOutputStream_Close(SEXP); extern SEXP FileOutputStream_Flush(SEXP); extern SEXP FileOutputStream_GetErrno(SEXP); extern SEXP FileOutputStream_new(SEXP, SEXP, SEXP); extern SEXP FileOutputStream_SetCloseOnDelete(SEXP, SEXP); /*extern SEXP get_method_input_type(SEXP);*/ extern SEXP get_method_output_prototype(SEXP); extern SEXP get_protobuf_library_version(); extern SEXP get_value_of_enum(SEXP, SEXP); extern SEXP getEnumDescriptor(SEXP); extern SEXP getExtension_cpp(SEXP, SEXP); extern SEXP getExtensionDescriptor(SEXP); extern SEXP getMessageField(SEXP, SEXP); extern SEXP getProtobufDescriptor(SEXP); extern SEXP has_enum_name(SEXP, SEXP); extern SEXP identical_messages(SEXP, SEXP); extern SEXP Message__add_values(SEXP, SEXP, SEXP); extern SEXP Message__as_character(SEXP); extern SEXP Message__as_list(SEXP); extern SEXP Message__bytesize(SEXP); extern SEXP Message__clear(SEXP); extern SEXP Message__clear_field(SEXP, SEXP); extern SEXP Message__clone(SEXP); /*extern SEXP Message__clone(SEXP, SEXP);*/ extern SEXP Message__descriptor(SEXP); extern SEXP Message__field_exists(SEXP, SEXP); extern SEXP Message__field_size(SEXP, SEXP); extern SEXP Message__fieldNames(SEXP); extern SEXP Message__fileDescriptor(SEXP); extern SEXP Message__get_field_values(SEXP, SEXP, SEXP); extern SEXP Message__get_payload(SEXP); extern SEXP Message__has_field(SEXP, SEXP); extern SEXP Message__is_initialized(SEXP); extern SEXP Message__length(SEXP); extern SEXP Message__merge(SEXP, SEXP); extern SEXP Message__num_extensions(SEXP); extern SEXP Message__serialize_to_file(SEXP, SEXP); extern SEXP Message__set_field_size(SEXP, SEXP, SEXP); extern SEXP Message__set_field_values(SEXP, SEXP, SEXP, SEXP); extern SEXP Message__swap(SEXP, SEXP, SEXP, SEXP); extern SEXP MethodDescriptor__as_character(SEXP); extern SEXP MethodDescriptor__as_Message(SEXP); extern SEXP MethodDescriptor__fileDescriptor(SEXP); extern SEXP MethodDescriptor__input_type(SEXP); extern SEXP MethodDescriptor__name(SEXP, SEXP); extern SEXP MethodDescriptor__output_type(SEXP); extern SEXP newProtocolBufferLookup(SEXP); extern SEXP newProtoMessage(SEXP); extern SEXP readProtoFiles_cpp(SEXP, SEXP); extern SEXP ServiceDescriptor__as_character(SEXP); extern SEXP ServiceDescriptor__as_list(SEXP); extern SEXP ServiceDescriptor__as_Message(SEXP); extern SEXP ServiceDescriptor__fileDescriptor(SEXP); extern SEXP ServiceDescriptor__getMethodNames(SEXP); /*extern SEXP ServiceDescriptor__method(SEXP, SEXP);*/ extern SEXP ServiceDescriptor__name(SEXP, SEXP); /*extern SEXP ServiceDescriptor_getMethodByIndex(SEXP, SEXP);*/ /*extern SEXP ServiceDescriptor_getMethodByName(SEXP, SEXP);*/ /*extern SEXP ServiceDescriptor_method_count(SEXP);*/ extern SEXP setMessageField(SEXP, SEXP, SEXP); extern SEXP update_message(SEXP, SEXP); extern SEXP valid_input_message(SEXP, SEXP); extern SEXP valid_output_message(SEXP, SEXP); extern SEXP ZeroCopyInputStream_BackUp(SEXP, SEXP); extern SEXP ZeroCopyInputStream_ByteCount(SEXP); extern SEXP ZeroCopyInputStream_Next(SEXP); extern SEXP ZeroCopyInputStream_ReadLittleEndian32(SEXP); extern SEXP ZeroCopyInputStream_ReadLittleEndian64(SEXP); extern SEXP ZeroCopyInputStream_ReadRaw(SEXP, SEXP); extern SEXP ZeroCopyInputStream_ReadString(SEXP, SEXP); extern SEXP ZeroCopyInputStream_ReadVarint32(SEXP); extern SEXP ZeroCopyInputStream_ReadVarint64(SEXP); extern SEXP ZeroCopyInputStream_Skip(SEXP, SEXP); extern SEXP ZeroCopyOutputStream_BackUp(SEXP, SEXP); extern SEXP ZeroCopyOutputStream_ByteCount(SEXP); extern SEXP ZeroCopyOutputStream_Next(SEXP, SEXP); extern SEXP ZeroCopyOutputStream_WriteLittleEndian32(SEXP, SEXP); extern SEXP ZeroCopyOutputStream_WriteLittleEndian64(SEXP, SEXP); extern SEXP ZeroCopyOutputStream_WriteRaw(SEXP, SEXP); extern SEXP ZeroCopyOutputStream_WriteString(SEXP, SEXP); extern SEXP ZeroCopyOutputStream_WriteVarint32(SEXP, SEXP); extern SEXP ZeroCopyOutputStream_WriteVarint64(SEXP, SEXP); static const R_CallMethodDef CallEntries[] = { {"all_equal_messages", (DL_FUNC) &all_equal_messages, 3}, {"ArrayInputStream__new", (DL_FUNC) &ArrayInputStream__new, 2}, {"ArrayOutputStream__new", (DL_FUNC) &ArrayOutputStream__new, 2}, {"ConnectionInputStream_new", (DL_FUNC) &ConnectionInputStream_new, 2}, {"ConnectionOutputStream_new", (DL_FUNC) &ConnectionOutputStream_new, 2}, {"Descriptor__as_character", (DL_FUNC) &Descriptor__as_character, 1}, {"Descriptor__as_list", (DL_FUNC) &Descriptor__as_list, 1}, {"Descriptor__as_Message", (DL_FUNC) &Descriptor__as_Message, 1}, {"Descriptor__containing_type", (DL_FUNC) &Descriptor__containing_type, 1}, {"Descriptor__enum_type", (DL_FUNC) &Descriptor__enum_type, 2}, {"Descriptor__enum_type_count", (DL_FUNC) &Descriptor__enum_type_count, 1}, {"Descriptor__field", (DL_FUNC) &Descriptor__field, 2}, {"Descriptor__field_count", (DL_FUNC) &Descriptor__field_count, 1}, {"Descriptor__fileDescriptor", (DL_FUNC) &Descriptor__fileDescriptor, 1}, /* {"Descriptor__FindEnumTypeByName", (DL_FUNC) &Descriptor__FindEnumTypeByName, 2}, */ {"Descriptor__FindFieldByName", (DL_FUNC) &Descriptor__FindFieldByName, 2}, {"Descriptor__FindFieldByNumber", (DL_FUNC) &Descriptor__FindFieldByNumber, 2}, {"Descriptor__FindNestedTypeByName", (DL_FUNC) &Descriptor__FindNestedTypeByName, 2}, {"Descriptor__getMemberNames", (DL_FUNC) &Descriptor__getMemberNames, 1}, {"Descriptor__name", (DL_FUNC) &Descriptor__name, 2}, {"Descriptor__nested_type", (DL_FUNC) &Descriptor__nested_type, 2}, {"Descriptor__nested_type_count", (DL_FUNC) &Descriptor__nested_type_count, 1}, {"Descriptor__readASCIIFromConnection", (DL_FUNC) &Descriptor__readASCIIFromConnection, 3}, {"Descriptor__readASCIIFromString", (DL_FUNC) &Descriptor__readASCIIFromString, 3}, {"Descriptor__readMessageFromConnection", (DL_FUNC) &Descriptor__readMessageFromConnection, 2}, {"Descriptor__readMessageFromFile", (DL_FUNC) &Descriptor__readMessageFromFile, 2}, {"Descriptor__readMessageFromRawVector", (DL_FUNC) &Descriptor__readMessageFromRawVector, 2}, {"Descriptor_getField", (DL_FUNC) &Descriptor_getField, 2}, {"do_dollar_Descriptor", (DL_FUNC) &do_dollar_Descriptor, 2}, {"EnumDescriptor__as_character", (DL_FUNC) &EnumDescriptor__as_character, 1}, {"EnumDescriptor__as_list", (DL_FUNC) &EnumDescriptor__as_list, 1}, {"EnumDescriptor__as_Message", (DL_FUNC) &EnumDescriptor__as_Message, 1}, {"EnumDescriptor__containing_type", (DL_FUNC) &EnumDescriptor__containing_type, 1}, {"EnumDescriptor__fileDescriptor", (DL_FUNC) &EnumDescriptor__fileDescriptor, 1}, {"EnumDescriptor__getConstantNames", (DL_FUNC) &EnumDescriptor__getConstantNames, 1}, {"EnumDescriptor__getValueByIndex", (DL_FUNC) &EnumDescriptor__getValueByIndex, 2}, {"EnumDescriptor__getValueByName", (DL_FUNC) &EnumDescriptor__getValueByName, 2}, {"EnumDescriptor__getValueByNumber", (DL_FUNC) &EnumDescriptor__getValueByNumber, 2}, {"EnumDescriptor__length", (DL_FUNC) &EnumDescriptor__length, 1}, {"EnumDescriptor__name", (DL_FUNC) &EnumDescriptor__name, 2}, {"EnumDescriptor__value_count", (DL_FUNC) &EnumDescriptor__value_count, 1}, {"EnumValueDescriptor__as_character", (DL_FUNC) &EnumValueDescriptor__as_character, 1}, {"EnumValueDescriptor__as_Message", (DL_FUNC) &EnumValueDescriptor__as_Message, 1}, {"EnumValueDescriptor__enum_type", (DL_FUNC) &EnumValueDescriptor__enum_type, 1}, {"EnumValueDescriptor__number", (DL_FUNC) &EnumValueDescriptor__number, 1}, {"FieldDescriptor__as_character", (DL_FUNC) &FieldDescriptor__as_character, 1}, {"FieldDescriptor__as_Message", (DL_FUNC) &FieldDescriptor__as_Message, 1}, {"FieldDescriptor__containing_type", (DL_FUNC) &FieldDescriptor__containing_type, 1}, {"FieldDescriptor__cpp_type", (DL_FUNC) &FieldDescriptor__cpp_type, 1}, {"FieldDescriptor__default_value", (DL_FUNC) &FieldDescriptor__default_value, 1}, {"FieldDescriptor__enum_type", (DL_FUNC) &FieldDescriptor__enum_type, 1}, {"FieldDescriptor__fileDescriptor", (DL_FUNC) &FieldDescriptor__fileDescriptor, 1}, {"FieldDescriptor__has_default_value", (DL_FUNC) &FieldDescriptor__has_default_value, 1}, {"FieldDescriptor__is_extension", (DL_FUNC) &FieldDescriptor__is_extension, 1}, {"FieldDescriptor__is_optional", (DL_FUNC) &FieldDescriptor__is_optional, 1}, {"FieldDescriptor__is_repeated", (DL_FUNC) &FieldDescriptor__is_repeated, 1}, {"FieldDescriptor__is_required", (DL_FUNC) &FieldDescriptor__is_required, 1}, {"FieldDescriptor__label", (DL_FUNC) &FieldDescriptor__label, 1}, {"FieldDescriptor__message_type", (DL_FUNC) &FieldDescriptor__message_type, 1}, {"FieldDescriptor__name", (DL_FUNC) &FieldDescriptor__name, 2}, {"FieldDescriptor__number", (DL_FUNC) &FieldDescriptor__number, 1}, {"FieldDescriptor__type", (DL_FUNC) &FieldDescriptor__type, 1}, {"FileDescriptor__as_character", (DL_FUNC) &FileDescriptor__as_character, 1}, {"FileDescriptor__as_list", (DL_FUNC) &FileDescriptor__as_list, 1}, {"FileDescriptor__as_Message", (DL_FUNC) &FileDescriptor__as_Message, 1}, {"FileDescriptor__getMemberNames", (DL_FUNC) &FileDescriptor__getMemberNames, 1}, {"FileDescriptor__name", (DL_FUNC) &FileDescriptor__name, 1}, {"FileInputStream_Close", (DL_FUNC) &FileInputStream_Close, 1}, {"FileInputStream_GetErrno", (DL_FUNC) &FileInputStream_GetErrno, 1}, {"FileInputStream_new", (DL_FUNC) &FileInputStream_new, 3}, {"FileInputStream_SetCloseOnDelete", (DL_FUNC) &FileInputStream_SetCloseOnDelete, 2}, {"FileOutputStream_Close", (DL_FUNC) &FileOutputStream_Close, 1}, {"FileOutputStream_Flush", (DL_FUNC) &FileOutputStream_Flush, 1}, {"FileOutputStream_GetErrno", (DL_FUNC) &FileOutputStream_GetErrno, 1}, {"FileOutputStream_new", (DL_FUNC) &FileOutputStream_new, 3}, {"FileOutputStream_SetCloseOnDelete", (DL_FUNC) &FileOutputStream_SetCloseOnDelete, 2}, /* {"get_method_input_type", (DL_FUNC) &get_method_input_type, 1},*/ {"get_method_output_prototype", (DL_FUNC) &get_method_output_prototype, 1}, {"get_protobuf_library_version", (DL_FUNC) &get_protobuf_library_version, 0}, {"get_value_of_enum", (DL_FUNC) &get_value_of_enum, 2}, {"getEnumDescriptor", (DL_FUNC) &getEnumDescriptor, 1}, {"getExtension_cpp", (DL_FUNC) &getExtension_cpp, 2}, {"getExtensionDescriptor", (DL_FUNC) &getExtensionDescriptor, 1}, {"getMessageField", (DL_FUNC) &getMessageField, 2}, {"getProtobufDescriptor", (DL_FUNC) &getProtobufDescriptor, 1}, {"has_enum_name", (DL_FUNC) &has_enum_name, 2}, {"identical_messages", (DL_FUNC) &identical_messages, 2}, {"Message__add_values", (DL_FUNC) &Message__add_values, 3}, {"Message__as_character", (DL_FUNC) &Message__as_character, 1}, {"Message__as_list", (DL_FUNC) &Message__as_list, 1}, {"Message__bytesize", (DL_FUNC) &Message__bytesize, 1}, {"Message__clear", (DL_FUNC) &Message__clear, 1}, {"Message__clear_field", (DL_FUNC) &Message__clear_field, 2}, {"Message__clone", (DL_FUNC) &Message__clone, 1}, /* {"Message__clone", (DL_FUNC) &Message__clone, 2},*/ {"Message__descriptor", (DL_FUNC) &Message__descriptor, 1}, {"Message__field_exists", (DL_FUNC) &Message__field_exists, 2}, {"Message__field_size", (DL_FUNC) &Message__field_size, 2}, {"Message__fieldNames", (DL_FUNC) &Message__fieldNames, 1}, {"Message__fileDescriptor", (DL_FUNC) &Message__fileDescriptor, 1}, {"Message__get_field_values", (DL_FUNC) &Message__get_field_values, 3}, {"Message__get_payload", (DL_FUNC) &Message__get_payload, 1}, {"Message__has_field", (DL_FUNC) &Message__has_field, 2}, {"Message__is_initialized", (DL_FUNC) &Message__is_initialized, 1}, {"Message__length", (DL_FUNC) &Message__length, 1}, {"Message__merge", (DL_FUNC) &Message__merge, 2}, {"Message__num_extensions", (DL_FUNC) &Message__num_extensions, 1}, {"Message__serialize_to_file", (DL_FUNC) &Message__serialize_to_file, 2}, {"Message__set_field_size", (DL_FUNC) &Message__set_field_size, 3}, {"Message__set_field_values", (DL_FUNC) &Message__set_field_values, 4}, {"Message__swap", (DL_FUNC) &Message__swap, 4}, {"MethodDescriptor__as_character", (DL_FUNC) &MethodDescriptor__as_character, 1}, {"MethodDescriptor__as_Message", (DL_FUNC) &MethodDescriptor__as_Message, 1}, {"MethodDescriptor__fileDescriptor", (DL_FUNC) &MethodDescriptor__fileDescriptor, 1}, {"MethodDescriptor__input_type", (DL_FUNC) &MethodDescriptor__input_type, 1}, {"MethodDescriptor__name", (DL_FUNC) &MethodDescriptor__name, 2}, {"MethodDescriptor__output_type", (DL_FUNC) &MethodDescriptor__output_type, 1}, {"newProtocolBufferLookup", (DL_FUNC) &newProtocolBufferLookup, 1}, {"newProtoMessage", (DL_FUNC) &newProtoMessage, 1}, {"readProtoFiles_cpp", (DL_FUNC) &readProtoFiles_cpp, 2}, {"ServiceDescriptor__as_character", (DL_FUNC) &ServiceDescriptor__as_character, 1}, {"ServiceDescriptor__as_list", (DL_FUNC) &ServiceDescriptor__as_list, 1}, {"ServiceDescriptor__as_Message", (DL_FUNC) &ServiceDescriptor__as_Message, 1}, {"ServiceDescriptor__fileDescriptor", (DL_FUNC) &ServiceDescriptor__fileDescriptor, 1}, {"ServiceDescriptor__getMethodNames", (DL_FUNC) &ServiceDescriptor__getMethodNames, 1}, /* {"ServiceDescriptor__method", (DL_FUNC) &ServiceDescriptor__method, 2},*/ {"ServiceDescriptor__name", (DL_FUNC) &ServiceDescriptor__name, 2}, /* {"ServiceDescriptor_getMethodByIndex", (DL_FUNC) &ServiceDescriptor_getMethodByIndex, 2},*/ /* {"ServiceDescriptor_getMethodByName", (DL_FUNC) &ServiceDescriptor_getMethodByName, 2},*/ /* {"ServiceDescriptor_method_count", (DL_FUNC) &ServiceDescriptor_method_count, 1},*/ {"setMessageField", (DL_FUNC) &setMessageField, 3}, {"update_message", (DL_FUNC) &update_message, 2}, {"valid_input_message", (DL_FUNC) &valid_input_message, 2}, {"valid_output_message", (DL_FUNC) &valid_output_message, 2}, {"ZeroCopyInputStream_BackUp", (DL_FUNC) &ZeroCopyInputStream_BackUp, 2}, {"ZeroCopyInputStream_ByteCount", (DL_FUNC) &ZeroCopyInputStream_ByteCount, 1}, {"ZeroCopyInputStream_Next", (DL_FUNC) &ZeroCopyInputStream_Next, 1}, {"ZeroCopyInputStream_ReadLittleEndian32", (DL_FUNC) &ZeroCopyInputStream_ReadLittleEndian32, 1}, {"ZeroCopyInputStream_ReadLittleEndian64", (DL_FUNC) &ZeroCopyInputStream_ReadLittleEndian64, 1}, {"ZeroCopyInputStream_ReadRaw", (DL_FUNC) &ZeroCopyInputStream_ReadRaw, 2}, {"ZeroCopyInputStream_ReadString", (DL_FUNC) &ZeroCopyInputStream_ReadString, 2}, {"ZeroCopyInputStream_ReadVarint32", (DL_FUNC) &ZeroCopyInputStream_ReadVarint32, 1}, {"ZeroCopyInputStream_ReadVarint64", (DL_FUNC) &ZeroCopyInputStream_ReadVarint64, 1}, {"ZeroCopyInputStream_Skip", (DL_FUNC) &ZeroCopyInputStream_Skip, 2}, {"ZeroCopyOutputStream_BackUp", (DL_FUNC) &ZeroCopyOutputStream_BackUp, 2}, {"ZeroCopyOutputStream_ByteCount", (DL_FUNC) &ZeroCopyOutputStream_ByteCount, 1}, {"ZeroCopyOutputStream_Next", (DL_FUNC) &ZeroCopyOutputStream_Next, 2}, {"ZeroCopyOutputStream_WriteLittleEndian32", (DL_FUNC) &ZeroCopyOutputStream_WriteLittleEndian32, 2}, {"ZeroCopyOutputStream_WriteLittleEndian64", (DL_FUNC) &ZeroCopyOutputStream_WriteLittleEndian64, 2}, {"ZeroCopyOutputStream_WriteRaw", (DL_FUNC) &ZeroCopyOutputStream_WriteRaw, 2}, {"ZeroCopyOutputStream_WriteString", (DL_FUNC) &ZeroCopyOutputStream_WriteString, 2}, {"ZeroCopyOutputStream_WriteVarint32", (DL_FUNC) &ZeroCopyOutputStream_WriteVarint32, 2}, {"ZeroCopyOutputStream_WriteVarint64", (DL_FUNC) &ZeroCopyOutputStream_WriteVarint64, 2}, {NULL, NULL, 0} }; void R_init_RProtoBuf(DllInfo *dll) { R_registerRoutines(dll, NULL, CallEntries, NULL, NULL); R_useDynamicSymbols(dll, FALSE); } RProtoBuf/src/extensions.cpp0000644000176200001440000000356713164671424015651 0ustar liggesusers/* -*- indent-tabs-mode: nil; tab-width: 4; show-trailing-whitespace: t; c-indent-level: 4; c-basic-offset: 4; -*- * Copyright 2012 Google Inc. All Rights Reserved. * Author: Murray Stokely * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. * */ #include "rprotobuf.h" #include "Rcppsupport.h" namespace rprotobuf { RcppExport SEXP getExtension_cpp(SEXP pointer, SEXP sfielddesc) { /* grab the Message pointer */ Rcpp::XPtr message(pointer); const GPB::Reflection* ref = message->GetReflection(); const GPB::FieldDescriptor* field_desc = GET_FIELD_DESCRIPTOR_POINTER_FROM_S4(sfielddesc); // extractFieldAsSEXP returns a default (e.g. 0) even when // field doesn't exist, but returning NULL probably makes more // sense. // // TODO(mstokely): move this logic into extractField so that // all fields get this updated behavior, not just extensions. if (field_desc->is_repeated()) { if (ref->FieldSize(*message, field_desc) < 1) { return R_NilValue; } } else { if (!ref->HasField(*message, field_desc)) { return R_NilValue; } } return (extractFieldAsSEXP(message, field_desc)); } } // namespace rprotobuf RProtoBuf/src/ConnectionCopyingOutputStream.h0000644000176200001440000000124013164671424021126 0ustar liggesusers#ifndef RPROTOBUF_ConnectionCopyingOutputStream_H #define RPROTOBUF_ConnectionCopyingOutputStream_H namespace rprotobuf { class ConnectionCopyingOutputStream : public GPB::io::CopyingOutputStream { public: ConnectionCopyingOutputStream(SEXP con); bool Write(const void* buffer, int size); private: /* the actual connection object from R it is protected by the external pointer that wraps the ConnectionInputStream, which is the only thing that uses this class, so we don't need to take care of GC here */ SEXP con; Rcpp::Function writeBin; }; } // namespace rprotobuf #endif RProtoBuf/src/mutators.cpp0000644000176200001440000012527413164671424015330 0ustar liggesusers// -*- indent-tabs-mode: nil; tab-width: 4; show-trailing-whitespace: t; c-indent-level: 4; c-basic-offset: 4; -*- // Copyright (C) 2010 - 2011 Dirk Eddelbuettel and Romain Francois // // This file is part of RProtoBuf. // // RProtoBuf is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // RProtoBuf is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with RProtoBuf. If not, see . #include "rprotobuf.h" #include "fieldtypes.h" #include "RcppMacros.h" namespace rprotobuf { // {{{ GETDOUBLE /** * get the index'th value of x, as an double * * @param x some R data * @param index the index * @return x[index], as an double * @throws Rcpp::exception if x[index] cannot be converted to double */ /* FIXME: should we convert the NA's */ double GET_double(SEXP x, int index) { switch (TYPEOF(x)) { case INTSXP: return ((double)INTEGER(x)[index]); case REALSXP: return (REAL(x)[index]); case LGLSXP: return ((double)LOGICAL(x)[index]); case RAWSXP: return ((double)RAW(x)[index]); default: Rcpp::stop("cannot cast SEXP to double"); } return 0.0; // -Wall } // }}} float GET_float(SEXP x, int index) { switch (TYPEOF(x)) { case INTSXP: return ((float)INTEGER(x)[index]); case REALSXP: return ((float)REAL(x)[index]); case LGLSXP: return ((float)LOGICAL(x)[index]); case RAWSXP: return ((float)RAW(x)[index]); default: Rcpp::stop("cannot cast SEXP to double"); } return (float)0.0; // -Wall } int GET_int(SEXP x, int index) { switch (TYPEOF(x)) { case INTSXP: return (INTEGER(x)[index]); case REALSXP: return ((int)REAL(x)[index]); case LGLSXP: return ((int)LOGICAL(x)[index]); case RAWSXP: return ((int)RAW(x)[index]); default: Rcpp::stop("cannot cast SEXP to int"); } return 0; // -Wall, should not happen since we only call this when we know it works } template ValueType Int64FromString(const std::string& value) { std::stringstream ss(value); ValueType ret; if ((ss >> ret).fail() || !(ss >> std::ws).eof()) { std::string message = "Provided character value '" + value + "' cannot be cast to 64-bit integer."; Rcpp::stop(message.c_str()); } return ret; } template ValueType Int32FromString(const std::string& value) { std::stringstream ss(value); ValueType ret; if ((ss >> ret).fail() || !(ss >> std::ws).eof()) { std::string message = "Provided character value '" + value + "' cannot be cast to 32-bit integer."; Rcpp::stop(message.c_str()); } return ret; } int32 GET_int32(SEXP x, R_xlen_t vec_index) { switch (TYPEOF(x)) { case INTSXP: return ((int32)INTEGER(x)[vec_index]); case REALSXP: return ((int32)REAL(x)[vec_index]); case LGLSXP: return ((int32)LOGICAL(x)[vec_index]); case RAWSXP: return ((int32)RAW(x)[vec_index]); case STRSXP: return Int32FromString(CHAR(STRING_ELT(x, vec_index))); default: Rcpp::stop("cannot cast SEXP to int32"); } return (int32)0; // -Wall, should not happen since we only call this when we know it works } int64 GET_int64(SEXP x, R_xlen_t vec_index) { switch (TYPEOF(x)) { case INTSXP: return ((int64)INTEGER(x)[vec_index]); case REALSXP: return ((int64)REAL(x)[vec_index]); case LGLSXP: return ((int64)LOGICAL(x)[vec_index]); case RAWSXP: return ((int64)RAW(x)[vec_index]); case STRSXP: return Int64FromString(CHAR(STRING_ELT(x, vec_index))); default: Rcpp::stop("cannot cast SEXP to int64"); } return (int64)0; // -Wall, should not happen since we only call this when we know it works } uint32 GET_uint32(SEXP x, R_xlen_t vec_index) { switch (TYPEOF(x)) { case INTSXP: return ((uint32)INTEGER(x)[vec_index]); case REALSXP: return ((uint32)REAL(x)[vec_index]); case LGLSXP: return ((uint32)LOGICAL(x)[vec_index]); case RAWSXP: return ((uint32)RAW(x)[vec_index]); case STRSXP: return Int32FromString(CHAR(STRING_ELT(x, vec_index))); default: Rcpp::stop("cannot cast SEXP to uint32"); } return (uint32)0; // -Wall, should not happen since we only call this when we know it works } uint64 GET_uint64(SEXP x, R_xlen_t vec_index) { switch (TYPEOF(x)) { case INTSXP: return ((uint64)INTEGER(x)[vec_index]); case REALSXP: return ((uint64)REAL(x)[vec_index]); case LGLSXP: return ((uint64)LOGICAL(x)[vec_index]); case RAWSXP: return ((uint64)RAW(x)[vec_index]); case STRSXP: return Int64FromString(CHAR(STRING_ELT(x, vec_index))); default: Rcpp::stop("cannot cast SEXP to uint64"); } return (uint64)0; // -Wall, should not happen since we only call this when we know it works } bool GET_bool(SEXP x, R_xlen_t vec_index) { switch (TYPEOF(x)) { case INTSXP: if (INTEGER(x)[vec_index] == R_NaInt) { Rcpp::stop("NA boolean values can not be stored in bool protocol buffer fields"); } return ((bool)INTEGER(x)[vec_index]); case REALSXP: if (REAL(x)[vec_index] == R_NaReal) { Rcpp::stop("NA boolean values can not be stored in bool protocol buffer fields"); } return ((bool)REAL(x)[vec_index]); case LGLSXP: if (LOGICAL(x)[vec_index] == NA_LOGICAL) { Rcpp::stop("NA boolean values can not be stored in bool protocol buffer fields"); } return ((bool)LOGICAL(x)[vec_index]); case RAWSXP: return ((bool)RAW(x)[vec_index]); default: Rcpp::stop("cannot cast SEXP to bool"); } return (bool)0; // Unreachable. -Wall } std::string GET_stdstring(SEXP x, R_xlen_t vec_index) { if (TYPEOF(x) == STRSXP) { return (CHAR(STRING_ELT(x, vec_index))); } return ""; // Unreachable. -Wall } std::string GET_bytes(SEXP x, R_xlen_t vec_index) { switch (TYPEOF(x)) { case RAWSXP: if (vec_index == 0) { return (std::string((const char*)RAW(x), (size_t)LENGTH(x))); } else { Rcpp::stop("cannot cast SEXP to bytes"); } case VECSXP: if (TYPEOF(VECTOR_ELT(x, vec_index)) == RAWSXP) { return (std::string((const char*)RAW(VECTOR_ELT(x, vec_index)), (size_t)LENGTH(VECTOR_ELT(x, vec_index)))); } else { Rcpp::stop("cannot cast SEXP to bytes"); } default: Rcpp::stop("cannot cast SEXP to bytes"); } return ""; // Unreachable. -Wall } /** * indicates if this is a list of messages * * @param x a list (VECSXP), not a long vec * @return TRUE if all objects are instances of Message class */ Rboolean allAreMessages(SEXP x) { if (TYPEOF(x) != VECSXP) return _FALSE_; R_xlen_t n = LENGTH(x); // Caller verifies its not a long vec SEXP current; for (R_xlen_t i = 0; i < n; i++) { current = VECTOR_ELT(x, i); /* not an S4 object */ if (TYPEOF(current) != S4SXP) return _FALSE_; /* not a Message object */ if (!Rf_inherits(current, "Message")) return _FALSE_; } return _TRUE_; } /** * indicates if this is a list of raws * * @param x a list (VECSXP) * @return TRUE if all objects are instances of RAWSXP */ Rboolean allAreRaws(SEXP x) { if (TYPEOF(x) != VECSXP) return _FALSE_; R_xlen_t n = LENGTH(x); SEXP current; for (R_xlen_t i = 0; i < n; i++) { current = VECTOR_ELT(x, i); /* not a RAWSXP */ if (TYPEOF(current) != RAWSXP) return _FALSE_; } return _TRUE_; } /** * check that all the values contained in value are suitable for the * enum type * * @param field_desc field descriptor of an enum type * @param value value to potentially fill the enum * */ void CHECK_values_for_enum(const GPB::FieldDescriptor* field_desc, SEXP value) { BEGIN_RCPP const GPB::EnumDescriptor* enum_desc = field_desc->enum_type(); // N.B. n undefined if TYPEOF(value) not a vector, but we catch that below. R_xlen_t n = XLENGTH(value); switch (TYPEOF(value)) { // {{{ numbers case INTSXP: case REALSXP: case LGLSXP: case RAWSXP: { int nenums = enum_desc->value_count(); // Guaranteed to be > 0. std::vector possibles(nenums); for (int i = 0; i < nenums; i++) { possibles[i] = enum_desc->value(i)->number(); } /* loop around the numbers to see if they are in the possibles */ for (int i = 0; i < n; i++) { int val = GET_int(value, i); int ok = 0; for (int j = 0; j < nenums; j++) { if (val == possibles[j]) { ok = 1; break; } } if (!ok) { Rcpp::stop("wrong value for enum"); } } break; } // }}} // {{{ STRSXP case STRSXP: { int nenums = enum_desc->value_count(); std::vector possibles(nenums); for (int i = 0; i < nenums; i++) { possibles[i] = enum_desc->value(i)->name(); } /* loop around the numbers to see if they are in the possibles */ for (int i = 0; i < n; i++) { const char* val = CHAR(STRING_ELT(value, i)); int ok = 0; /* FIXME: there is probably something more efficient */ for (int j = 0; j < nenums; j++) { if (!possibles[j].compare(val)) { ok = 1; break; } } if (!ok) { Rcpp::stop("wrong value for enum"); } } break; } // }}} default: Rcpp::stop("impossible to convert to a enum"); } VOID_END_RCPP } /** * check that the values are suitable for the field descriptor * * @throws Rcpp::exception on error (uncaught) */ void CHECK_messages(const GPB::FieldDescriptor* field_desc, SEXP values) { if (TYPEOF(values) != VECSXP) { Rcpp::stop("expecting a list of messages"); } const char* target = field_desc->message_type()->full_name().c_str(); int n = LENGTH(values); for (int i = 0; i < n; i++) { if (!isMessage(VECTOR_ELT(values, i), target)) { // TODO(mstokely): When we have C++11 CXX11, use // std::to_string(i) // {{{ std::string s; std::stringstream out; out << i; s = out.str(); // }}} string message = "List element " + s + " is not a message " + "of the appropriate type ('" + target + "')"; Rcpp::stop(message.c_str()); } } } /** * check that all repeated values are ok before doing anything, * otherwise this could lead to modifying a few values then failing in * an inconsistent state. */ void CHECK_repeated_vals(const GPB::FieldDescriptor* field_desc, SEXP value, int value_size) { switch (field_desc->type()) { case TYPE_MESSAGE: case TYPE_GROUP: { switch (TYPEOF(value)) { case VECSXP: { /* check that it is a list of Messages of the appropriate type */ CHECK_messages(field_desc, value); break; } case S4SXP: { /* check that this is a message of the appropriate type */ if (!isMessage(value, field_desc->message_type()->full_name().c_str())) { string message = "Not a message of type '" + field_desc->message_type()->full_name() + "'"; Rcpp::stop(message.c_str()); } break; } default: Rcpp::stop("impossible to convert to a message"); } break; } case TYPE_ENUM: { const GPB::EnumDescriptor* enum_desc = field_desc->enum_type(); /* check first, it means we have to loop twice, but otherwise this could have some side effects before the exception is thrown */ /* FIXME: the checking should go before the resizing */ switch (TYPEOF(value)) { // {{{ numbers case INTSXP: case REALSXP: case LGLSXP: case RAWSXP: { int nenums = enum_desc->value_count(); std::vector possibles(nenums); for (int i = 0; i < nenums; i++) { possibles[i] = enum_desc->value(i)->number(); } /* loop around the numbers to see if they are in the possibles */ for (int i = 0; i < value_size; i++) { int val = GET_int(value, i); int ok = 0; for (int j = 0; j < nenums; j++) { if (val == possibles[j]) { ok = 1; break; } } if (!ok) { Rcpp::stop("wrong value for enum"); } } break; } // }}} // {{{ STRSXP case STRSXP: { int nenums = enum_desc->value_count(); std::vector possibles(nenums); for (int i = 0; i < nenums; i++) { possibles[i] = enum_desc->value(i)->name(); } /* loop around the numbers to see if they are in the possibles */ for (int i = 0; i < value_size; i++) { const char* val = CHAR(STRING_ELT(value, i)); int ok = 0; /* FIXME: there is probably something more efficient */ for (int j = 0; j < nenums; j++) { if (!possibles[j].compare(val)) { ok = 1; break; } } if (!ok) { Rcpp::stop("wrong value for enum"); } } break; } // }}} default: Rcpp::stop("impossible to convert to a enum"); } break; } case TYPE_DOUBLE: case TYPE_FLOAT: case TYPE_INT64: case TYPE_UINT64: case TYPE_INT32: case TYPE_FIXED64: case TYPE_FIXED32: case TYPE_BOOL: case TYPE_STRING: case TYPE_BYTES: case TYPE_UINT32: case TYPE_SFIXED32: case TYPE_SFIXED64: case TYPE_SINT32: case TYPE_SINT64: { ; // nothing, just to satisfy -Wall } } } /** * set a non-repeated message field to a new value * * @param message pointer to a message * @param ref pointer to reflection object for message * @param field_desc pointer to field descriptor to update * @param value new value for the field * @param value_size size of the new value for the field * @throws Rcpp::exception on error (uncaught) * @return void, the message is modified by reference */ void setNonRepeatedMessageField(GPB::Message* message, const Reflection* ref, const GPB::FieldDescriptor* field_desc, SEXP value, int value_size) { if (value_size > 1) { Rcpp::stop("cannot set non-repeated field to vector of length > 1"); } switch (GPB::FieldDescriptor::TypeToCppType(field_desc->type())) { // {{{ simple cases using macro expansion #undef HANDLE_SINGLE_FIELD #define HANDLE_SINGLE_FIELD(CPPTYPE, CAMEL, TYPE) \ case CPPTYPE: { \ ref->Set##CAMEL(message, field_desc, Rcpp::as(value)); \ break; \ } HANDLE_SINGLE_FIELD(CPPTYPE_DOUBLE, Double, double) HANDLE_SINGLE_FIELD(CPPTYPE_FLOAT, Float, float) case CPPTYPE_BOOL: { // TODO(mstokely): Rcpp should handle this! if ((TYPEOF(value) == LGLSXP) && (LOGICAL(value)[0] == NA_LOGICAL)) { Rcpp::stop("NA boolean values can not be stored in bool protocol buffer fields"); } else if ((TYPEOF(value) == INTSXP) && (INTEGER(value)[0] == R_NaInt)) { Rcpp::stop("NA boolean values can not be stored in bool protocol buffer fields"); } else if ((TYPEOF(value) == REALSXP) && (REAL(value)[0] == R_NaReal)) { Rcpp::stop("NA boolean values can not be stored in bool protocol buffer fields"); } ref->SetBool(message, field_desc, Rcpp::as(value)); break; } case CPPTYPE_INT32: { if (TYPEOF(value) == STRSXP) { const string int32str = COPYSTRING(CHAR(STRING_ELT(value, 0))); ref->SetInt32(message, field_desc, Int32FromString(int32str)); break; } else { ref->SetInt32(message, field_desc, Rcpp::as(value)); break; } } case CPPTYPE_UINT32: { if (TYPEOF(value) == STRSXP) { const string uint32str = COPYSTRING(CHAR(STRING_ELT(value, 0))); ref->SetUInt32(message, field_desc, Int32FromString(uint32str)); break; } else { // Rcpp::as is broken for uint32 types, so we just get Rcpp // to give us a valid double, ref->SetUInt32(message, field_desc, Rcpp::as(value)); break; } } #ifdef RCPP_HAS_LONG_LONG_TYPES case CPPTYPE_INT64: { // TODO(mstokely) Rcpp::as of a STRSEXP should just // work for strings representing int64s. if (TYPEOF(value) == STRSXP) { const string int64str = COPYSTRING(CHAR(STRING_ELT(value, 0))); ref->SetInt64(message, field_desc, Int64FromString(int64str)); break; } else { ref->SetInt64(message, field_desc, Rcpp::as(value)); break; } } case CPPTYPE_UINT64: { // TODO(mstokely) Rcpp::as of a STRSEXP should just // work for strings representing int64s. if (TYPEOF(value) == STRSXP) { const string int64str = COPYSTRING(CHAR(STRING_ELT(value, 0))); ref->SetUInt64(message, field_desc, Int64FromString(int64str)); break; } else { ref->SetUInt64(message, field_desc, Rcpp::as(value)); break; } } #endif #undef HANDLE_SINGLE_FIELD default: Rcpp::stop("Unsupported type"); // }}} // {{{ string case CPPTYPE_STRING: { switch (TYPEOF(value)) { case STRSXP: { ref->SetString(message, field_desc, COPYSTRING(CHAR(STRING_ELT(value, 0)))); break; } case RAWSXP: { ref->SetString(message, field_desc, GET_bytes(value, 0)); break; } case S4SXP: { /* check if value is a message */ if (!Rf_inherits(value, "Message")) { Rcpp::stop("Can only convert S4 objects of class 'Message'"); } GPB::Message* __mess = GET_MESSAGE_POINTER_FROM_S4(value); ref->SetString(message, field_desc, __mess->SerializeAsString()); break; } default: Rcpp::stop("Cannot convert to string"); } break; } // }}} // {{{ message case CPPTYPE_MESSAGE: { if (TYPEOF(value) == S4SXP && Rf_inherits(value, "Message")) { GPB::Message* mess = (GPB::Message*)EXTPTR_PTR(GET_SLOT(value, Rf_install("pointer"))); const char* type = mess->GetDescriptor()->full_name().c_str(); const char* target = field_desc->message_type()->full_name().c_str(); if (strcmp(type, target)) { Rcpp::stop("wrong message type"); } GPB::Message* m = ref->MutableMessage(message, field_desc); m->CopyFrom(*mess); } else { Rcpp::stop("type mismatch, expecting a 'Message' object"); } break; } // }}} // {{{ enum case CPPTYPE_ENUM: { const GPB::EnumDescriptor* enum_desc = field_desc->enum_type(); switch (TYPEOF(value)) { case INTSXP: case REALSXP: case LGLSXP: case RAWSXP: { int val = Rcpp::as(value); const GPB::EnumValueDescriptor* evd = enum_desc->FindValueByNumber(val); if (!evd) { Rcpp::stop("wrong value for enum"); } else { ref->SetEnum(message, field_desc, evd); } break; } case STRSXP: { std::string val = Rcpp::as(value); const GPB::EnumValueDescriptor* evd = enum_desc->FindValueByName(val); if (!evd) { Rcpp::stop("wrong value for enum"); } else { ref->SetEnum(message, field_desc, evd); } break; } default: Rcpp::stop("cannot set enum value"); } break; } // }}} } } /** * set a repeated message field to a new value * * @param message pointer to a message * @param ref pointer to reflection object for message * @param field_desc pointer to field descriptor to update * @param value new value for the field * @param value_size size of the new value for the field * @throws Rcpp::exception on error (uncaught) * @return void, the message is modified by reference */ void setRepeatedMessageField(GPB::Message* message, const Reflection* ref, const GPB::FieldDescriptor* field_desc, SEXP value, R_xlen_t value_size) { // The number of elements already in the repeated field. int field_size = ref->FieldSize(*message, field_desc); /* in case of messages or enum, we have to check that all values are ok before doing anything, othewise this could leed to modify a few values and then fail which is not good */ CHECK_repeated_vals(field_desc, value, value_size); /* Remove some items if there are too many. */ if (field_size > value_size) { /* we need to remove some */ while (field_size > value_size) { ref->RemoveLast(message, field_desc); field_size--; } } switch (field_desc->type()) { // {{{ int32 case TYPE_INT32: case TYPE_SINT32: case TYPE_SFIXED32: { switch (TYPEOF(value)) { case INTSXP: case REALSXP: case LGLSXP: case RAWSXP: case STRSXP: // For int32, we support chars. { R_xlen_t i = 0; /* in any case, fill the values up to field_size */ for (; i < field_size; i++) { ref->SetRepeatedInt32(message, field_desc, i, GET_int32(value, i)); } /* then add some if needed */ if (value_size > field_size) { for (; i < value_size; i++) { ref->AddInt32(message, field_desc, GET_int32(value, i)); } } break; } default: Rcpp::stop("Cannot convert to int32"); } break; } // }}} // {{{ int64 case TYPE_INT64: case TYPE_SINT64: case TYPE_SFIXED64: { switch (TYPEOF(value)) { case INTSXP: case REALSXP: case LGLSXP: case RAWSXP: case STRSXP: // For int64, we support chars. { R_xlen_t i = 0; /* in any case, fill the values up to field_size */ for (; i < field_size; i++) { ref->SetRepeatedInt64(message, field_desc, i, GET_int64(value, i)); } /* then add some if needed */ if (value_size > field_size) { for (; i < value_size; i++) { ref->AddInt64(message, field_desc, GET_int64(value, i)); } } break; } default: Rcpp::stop("Cannot convert to int64"); } break; } // }}} // {{{ uint32 case TYPE_UINT32: case TYPE_FIXED32: { switch (TYPEOF(value)) { case INTSXP: case REALSXP: case LGLSXP: case RAWSXP: case STRSXP: // For int32, we support chars. { R_xlen_t i = 0; /* in any case, fill the values up to field_size */ for (; i < field_size; i++) { ref->SetRepeatedUInt32(message, field_desc, i, GET_uint32(value, i)); } /* then add some if needed */ if (value_size > field_size) { for (; i < value_size; i++) { ref->AddUInt32(message, field_desc, GET_uint32(value, i)); } } break; } default: Rcpp::stop("Cannot convert to uint32"); } break; } // }}} // {{{ uint64 case TYPE_UINT64: case TYPE_FIXED64: { switch (TYPEOF(value)) { case INTSXP: case REALSXP: case LGLSXP: case RAWSXP: case STRSXP: // For int64, we support chars. { R_xlen_t i = 0; /* in any case, fill the values up to field_size */ for (; i < field_size; i++) { ref->SetRepeatedUInt64(message, field_desc, i, GET_uint64(value, i)); } /* then add some if needed */ if (value_size > field_size) { for (; i < value_size; i++) { ref->AddUInt64(message, field_desc, GET_uint64(value, i)); } } break; } default: Rcpp::stop("Cannot convert to int64"); } break; } // }}} // {{{ double case TYPE_DOUBLE: { switch (TYPEOF(value)) { case INTSXP: case REALSXP: case LGLSXP: case RAWSXP: { R_xlen_t i = 0; /* in any case, fill the values up to field_size */ for (; i < field_size; i++) { ref->SetRepeatedDouble(message, field_desc, i, GET_double(value, i)); } /* then add some if needed */ if (value_size > field_size) { for (; i < value_size; i++) { ref->AddDouble(message, field_desc, GET_double(value, i)); } } break; } default: Rcpp::stop("Cannot convert to double"); } break; } // }}} // {{{ float case TYPE_FLOAT: { switch (TYPEOF(value)) { case INTSXP: case REALSXP: case LGLSXP: case RAWSXP: { R_xlen_t i = 0; /* in any case, fill the values up to field_size */ for (; i < field_size; i++) { ref->SetRepeatedFloat(message, field_desc, i, GET_float(value, i)); } /* then add some if needed */ if (value_size > field_size) { for (; i < value_size; i++) { ref->AddFloat(message, field_desc, GET_float(value, i)); } } break; } default: Rcpp::stop("Cannot convert to float"); } break; } // }}} // {{{ bool case TYPE_BOOL: { switch (TYPEOF(value)) { case INTSXP: case REALSXP: case LGLSXP: case RAWSXP: { R_xlen_t i = 0; /* in any case, fill the values up to field_size */ for (; i < field_size; i++) { ref->SetRepeatedBool(message, field_desc, i, GET_bool(value, i)); } /* then add some if needed */ if (value_size > field_size) { for (; i < value_size; i++) { ref->AddBool(message, field_desc, GET_bool(value, i)); } } break; } default: Rcpp::stop("Cannot convert to bool"); } break; } // }}} // {{{ string case TYPE_STRING: case TYPE_BYTES: { switch (TYPEOF(value)) { case STRSXP: { /* in any case, fill the values up to field_size */ R_xlen_t i = 0; for (; i < field_size; i++) { ref->SetRepeatedString(message, field_desc, i, COPYSTRING(CHAR(STRING_ELT(value, i)))); } /* then add some if needed */ if (value_size > field_size) { for (; i < value_size; i++) { ref->AddString(message, field_desc, COPYSTRING(CHAR(STRING_ELT(value, i)))); } } break; } case RAWSXP: { /* in any case, fill the values up to field_size */ R_xlen_t i = 0; for (; i < field_size; i++) { ref->SetRepeatedString(message, field_desc, i, GET_bytes(value, 0)); } /* then add some if needed */ if (value_size > field_size) { for (; i < value_size; i++) { ref->AddString(message, field_desc, GET_bytes(value, 0)); } } break; } case S4SXP: { /* check if value is a message */ if (!Rf_inherits(value, "Message")) { Rcpp::stop("Can only convert S4 objects of class 'Message'"); } GPB::Message* __mess = GET_MESSAGE_POINTER_FROM_S4(value); ref->SetRepeatedString(message, field_desc, 0, __mess->SerializeAsString()); break; } case VECSXP: { // we know it is a list of messages or raws because it // has been tested above if (LENGTH(value) > 0 && TYPEOF(VECTOR_ELT(value, 0)) == RAWSXP) { /* in any case, fill the values up to field_size */ R_xlen_t i = 0; for (; i < field_size; i++) { ref->SetRepeatedString(message, field_desc, i, GET_bytes(value, i)); } /* then add some if needed */ if (value_size > field_size) { for (; i < value_size; i++) { ref->AddString(message, field_desc, GET_bytes(value, i)); } } } else { // FIXME: we should probably use SerializeToString // as indicated in the protobuf api documentation // http://code.google.com/apis/protocolbuffers/docs/reference/cpp/google.protobuf.message_lite.html#MessageLite.SerializeAsString.details GPB::Message* __mess; /* in any case, fill the values up to field_size */ R_xlen_t i = 0; for (; i < field_size; i++) { __mess = GET_MESSAGE_POINTER_FROM_S4(VECTOR_ELT(value, i)); ref->SetRepeatedString(message, field_desc, i, __mess->SerializeAsString()); } /* then add some if needed */ if (value_size > field_size) { for (; i < value_size; i++) { __mess = GET_MESSAGE_POINTER_FROM_S4(VECTOR_ELT(value, i)); ref->AddString(message, field_desc, __mess->SerializeAsString()); } } } break; } default: Rcpp::stop("Cannot convert to string"); } break; } // }}} // {{{ message case TYPE_MESSAGE: case TYPE_GROUP: { if (TYPEOF(value) == S4SXP) { /* we know it is a message of the correct type (tested above) */ GPB::Message* mess = GET_MESSAGE_POINTER_FROM_S4(value); if (field_size == 1) { /* FIXME: we should not __copy__ the message */ ref->MutableRepeatedMessage(message, field_desc, 0)->CopyFrom(*mess); } else { /* FIXME */ ref->ClearField(message, field_desc); /* FIXME: we should not __copy__ the message */ ref->AddMessage(message, field_desc)->CopyFrom(*mess); } } else if (TYPEOF(value) == VECSXP) { /* in any case, fill the values up to field_size */ int i = 0; for (; i < field_size; i++) { GPB::Message* mess = GET_MESSAGE_POINTER_FROM_S4(VECTOR_ELT(value, i)); /* we already know it is of the correct type because of the premptive check above */ ref->MutableRepeatedMessage(message, field_desc, i)->CopyFrom(*mess); } /* then add some if needed */ if (value_size > field_size) { for (; i < value_size; i++) { GPB::Message* mess = GET_MESSAGE_POINTER_FROM_S4(VECTOR_ELT(value, i)); /* we already know it is of the correct type because of the premptive check above */ ref->AddMessage(message, field_desc)->CopyFrom(*mess); } } } else { Rcpp::stop("type mismatch, expecting a 'Message' object or a list of them"); } break; } // }}} // {{{ enum case TYPE_ENUM: { const GPB::EnumDescriptor* enum_desc = field_desc->enum_type(); switch (TYPEOF(value)) { // {{{ numbers case INTSXP: case REALSXP: case LGLSXP: case RAWSXP: { int i = 0; /* in any case, fill the values up to field_size */ for (; i < field_size; i++) { int val = GET_int(value, i); ref->SetRepeatedEnum(message, field_desc, i, enum_desc->FindValueByNumber(val)); } /* then add some if needed */ if (value_size > field_size) { for (; i < value_size; i++) { int val = GET_int(value, i); ref->AddEnum(message, field_desc, enum_desc->FindValueByNumber(val)); } } break; } // }}} // {{{ STRSXP case STRSXP: { /* in any case, fill the values up to field_size */ int i = 0; for (; i < field_size; i++) { std::string val = CHAR(STRING_ELT(value, i)); const GPB::EnumValueDescriptor* evd = enum_desc->FindValueByName(val); ref->SetRepeatedEnum(message, field_desc, i, evd); } /* then add some if needed */ if (value_size > field_size) { for (; i < value_size; i++) { std::string val = CHAR(STRING_ELT(value, i)); const GPB::EnumValueDescriptor* evd = enum_desc->FindValueByName(val); ref->AddEnum(message, field_desc, evd); } } break; } // }}} default: Rcpp::stop("cannot set enum value"); } } // }}} } } /** * set a message field to a new value * * @param pointer external pointer to a message * @param name name of the field, or an S4 FieldDescriptor object. * @param value new value for the field * * @return allways NULL, the message is modified by reference */ SEXP setMessageField(SEXP pointer, SEXP name, SEXP value) { BEGIN_RCPP RPB_DEBUG_BEGIN("setMessageField") PRINT_DEBUG_INFO("pointer", pointer); PRINT_DEBUG_INFO("name", name); PRINT_DEBUG_INFO("value", value); /* grab the Message pointer */ GPB::Message* message = GET_MESSAGE_POINTER_FROM_XP(pointer); /* check that we can get a file descriptor from name */ const GPB::FieldDescriptor* field_desc = getFieldDescriptor(message, name); const Reflection* ref = message->GetReflection(); if (value == R_NilValue || (Rf_isVector(value) && LENGTH(value) == 0)) { ref->ClearField(message, field_desc); return R_NilValue; } // {{{ preliminary checks R_xlen_t value_size = 1; if (Rf_isVector(value)) { if (IS_LONG_VEC(value)) { // field_size is an int, so presumably it would generate // a CHECK failure in protobuf code on 2^32 element anyway. Rcpp_error("Long vectors not supported for repeated fields."); } else { value_size = LENGTH(value); } } // if the R type is RAWSXP and the cpp type is string or bytes, // then value_size is actually one because the raw vector // is converted to a string GPB::FieldDescriptor::Type field_type = field_desc->type(); if (field_type == TYPE_STRING || field_type == TYPE_BYTES) { if (TYPEOF(value) == RAWSXP) { value_size = 1; } else if (TYPEOF(value) == STRSXP) { value_size = LENGTH(value); } else if (TYPEOF(value) == S4SXP && Rf_inherits(value, "Message")) { value_size = 1; /* we will store the message payload */ } else if (TYPEOF(value) == VECSXP && allAreMessages(value)) { value_size = LENGTH(value); } else if (TYPEOF(value) == VECSXP && allAreRaws(value)) { value_size = LENGTH(value); } else { Rcpp::stop("cannot convert to string"); } } // }}} if (field_desc->is_repeated()) { setRepeatedMessageField(message, ref, field_desc, value, value_size); } else { setNonRepeatedMessageField(message, ref, field_desc, value, value_size); } RPB_DEBUG_END("setMessageField") END_RCPP } RPB_FUNCTION_VOID_2(update_message, Rcpp::XPtr message, Rcpp::List list) { Rcpp::CharacterVector names = list.attr("names"); int n = list.size(); for (int i = 0; i < n; i++) { (void)setMessageField(message, names[i], list[i]); } } } // namespace rprotobuf RProtoBuf/src/RSourceTree.cpp0000644000176200001440000000315513164671424015645 0ustar liggesusers// -*- indent-tabs-mode: nil; tab-width: 4; show-trailing-whitespace: t; c-indent-level: 4; c-basic-offset: 4; -*- #include "rprotobuf.h" #include "RSourceTree.h" namespace rprotobuf { RSourceTree::RSourceTree() : directories() {} GPB::io::ZeroCopyInputStream* RSourceTree::Open(const std::string& filename) { /* first, try to open the file as it is */ int file_descriptor = open(filename.c_str(), O_RDONLY); if (file_descriptor < 0) { /* then try the directories */ std::set::iterator it; it = directories.begin(); std::string file; while (it != directories.end()) { file = *it; file += "/"; file += filename; file_descriptor = open(file.c_str(), O_RDONLY); if (file_descriptor > 0) break; ++it; } } if (file_descriptor < 0) { return NULL; } GPB::io::FileInputStream* result = new GPB::io::FileInputStream(file_descriptor); result->SetCloseOnDelete(true); return result; } void RSourceTree::addDirectory(const std::string& directory) { directories.insert(directory); } void RSourceTree::addDirectories(SEXP dirs) { int n = LENGTH(dirs); for (int i = 0; i < n; i++) { directories.insert(std::string(CHAR(STRING_ELT(dirs, i)))); } } void RSourceTree::removeDirectory(const std::string& directory) { directories.erase(directory); } void RSourceTree::removeDirectories(SEXP dirs) { int n = LENGTH(dirs); for (int i = 0; i < n; i++) { directories.erase(std::string(CHAR(STRING_ELT(dirs, i)))); } } } // namespace rprotobuf RProtoBuf/NAMESPACE0000644000176200001440000000602313144043463013356 0ustar liggesusers ## Package has dynamic library useDynLib("RProtoBuf", .registration=TRUE) importFrom("methods", "new", "show", "as", "is") importFrom("utils", "str", "packageDescription") importFrom("stats", "update") importFrom("tools", "file_path_as_absolute") importFrom("RCurl", "basicTextGatherer", "curlPerform") importFrom("Rcpp", "evalCpp") exportClasses( # descriptors "Descriptor", "FieldDescriptor", "EnumDescriptor", "ServiceDescriptor", "MethodDescriptor", "FileDescriptor", "EnumValueDescriptor", # message "Message", # rpc "RpcHTTP", # virtual streams "ZeroCopyInputStream", "ZeroCopyOutputStream", # concrete implementations "ArrayInputStream", "ArrayOutputStream", "FileInputStream", "FileOutputStream", "ConnectionInputStream", "ConnectionOutputStream" ) exportMethods( "new", "[[", "[[<-", "$", "$<-", "show", "serialize", "as.character", "update", "has", "clone", "merge", "read", "readASCII", "bytesize", "length", "str", "isInitialized", "clear", "size", "size<-", "swap", "descriptor", "set", "fetch", "toString", "identical", "==", "!=", "all.equal", "add", "fileDescriptor", "name", "names", "flush", "close", "setExtension", "getExtension", "containing_type", "field_count", "nested_type_count", "enum_type_count", "field", "nested_type", "enum_type", # FieldDescriptor "is_extension", "number", "label", "is_required", "is_repeated", "is_optional", "has_default_value", "default_value", "message_type", "enum_type", "type", "cpp_type", # EnumDescriptor "value_count", "value", # ServiceDescriptor "method_count", "method", # MethodDescriptor "input_type", "output_type", # rpc "invoke", # streams "Next", "ByteCount", "BackUp", "Skip", "ArrayInputStream", "ArrayOutputStream", "FileInputStream", "FileOutputStream", "GetErrno", "SetCloseOnDelete", "ConnectionInputStream", "ConnectionOutputStream", "ReadRaw", "ReadString", "ReadVarint32", "ReadLittleEndian32", "ReadLittleEndian64", "ReadVarint64", "WriteRaw", "WriteString", "WriteLittleEndian32", "WriteLittleEndian64", "WriteVarint32", "WriteVarint64" ) export( "P", "readProtoFiles", "asMessage" ) if( exists( ".DollarNames", asNamespace("utils") ) ) importFrom( utils, .DollarNames ) S3method(.DollarNames, Message ) S3method(.DollarNames, Descriptor ) S3method(.DollarNames, EnumDescriptor ) S3method(.DollarNames, EnumValueDescriptor ) S3method(.DollarNames, FileDescriptor ) S3method(.DollarNames, FieldDescriptor ) S3method(.DollarNames, ServiceDescriptor ) S3method(.DollarNames, MethodDescriptor ) S3method(.DollarNames, ZeroCopyInputStream ) S3method(.DollarNames, ZeroCopyOutputStream ) S3method( with, Message ) S3method( within, Message) S3method( as.list, Message ) S3method( as.list, Descriptor ) S3method( as.list, EnumDescriptor ) S3method( as.list, FileDescriptor ) S3method( as.list, ServiceDescriptor ) # constants exportPattern( "^TYPE_" ) exportPattern( "^CPPTYPE_" ) exportPattern( "^LABEL_" ) # copied from RProtoBufUtils export( "serialize_pb", "unserialize_pb", "can_serialize_pb" ) # export( run_unit_tests ) RProtoBuf/demo/0000755000176200001440000000000013005133352013053 5ustar liggesusersRProtoBuf/demo/io.R0000644000176200001440000000164413005133352013612 0ustar liggesusersrequire( RProtoBuf ) ### read messages from files and binary connections # read a message from a file name f <- system.file( "examples", "addressbook.pb", package = "RProtoBuf" ) m1 <- read( tutorial.AddressBook, f ) writeLines( as.character( m1 ) ) # read the same message from a (binary) file connection con <- file( f, open = "rb" ) m2 <- read( tutorial.AddressBook, con ) # this also works: # m2 <- tutorial.AddressBook$read( con ) writeLines( as.character( m2 ) ) close( con ) # TODO: we need another example from a more fancy connection (pipe, ...) stopifnot( identical( as.character(m1), as.character(m2) ) ) ### write messages to files and binary connections tf1 <- tempfile() serialize( m1, tf1 ) tf2 <- tempfile() con <- file( tf2, open = "wb" ) serialize( m2, con ) close( con ) # test that the two binary files are identical stopifnot( identical( readBin( tf1, raw(0), 1000), readBin( tf2, raw(0), 1000) ) ) RProtoBuf/demo/addressbook.R0000644000176200001440000000325013005133352015476 0ustar liggesusers# load the package require( RProtoBuf ) # read all the proto files in the proto directory # of the package "RProtoBuf" # (this is also done in the startup of the package, so this call is # actually redundant) readProtoFiles( package = "RProtoBuf" ) # creating three Person messages # create a prototype with a simple call to new on the # descriptor for the Person message type, and then update the message # with fields romain <- update( new( tutorial.Person ), email = "romain@r-enthusiasts.com", id = 1, name = "Romain Francois", phone = new( tutorial.Person.PhoneNumber , number = "+33(0)...", type = "MOBILE" ) ) # directly supply parameters to the constructor dirk <- new( tutorial.Person, email = "edd@debian.org", id = 2, name = "Dirk Eddelbuettel" ) # update the phone repeated field with a list of PhoneNumber messages dirk$phone <- list( new( tutorial.Person.PhoneNumber , number = "+01...", type = "MOBILE" ), new( tutorial.Person.PhoneNumber , number = "+01...", type = "HOME" ) ) # build the address book book <- new( tutorial.AddressBook, person = list( romain, dirk ) ) # debug string. This is not what is transferred in the wire writeLines( as.character( book ) ) # the serialized message # see also the io demo to see how to serialize messages to connections # and files serialize( book, NULL ) # number of bytes taken by the message on the wire bytesize( book ) length( serialize( book, NULL ) ) # swap two persons in the address book # (1-based indexing) book$swap( "person", 1L , 2L ) writeLines( as.character( book ) ) # number of "person" in the book book$size( "person" ) # clear the message book$clear( ) writeLines( as.character( book ) ) RProtoBuf/demo/00Index0000644000176200001440000000015313005133352014204 0ustar liggesusersaddressbook Demonstration of RProtoBuf functionality io Input/Output handling of protocol buffer messages RProtoBuf/R/0000755000176200001440000000000013144106760012337 5ustar liggesusersRProtoBuf/R/clear.R0000644000176200001440000000202213005133352013535 0ustar liggesuserssetGeneric( "clear", function(object, field, ...){ standardGeneric( "clear" ) } ) setMethod( "clear", signature( "Message", "missing" ), function(object, field, ...){ .Call( "Message__clear", object@pointer, PACKAGE = "RProtoBuf" ) invisible( object ) } ) setMethod( "clear", signature( "Message", "character" ), function(object, field, ...){ .Call( "Message__clear_field", object@pointer, field, PACKAGE = "RProtoBuf" ) invisible( object ) } ) setMethod( "clear", signature( "Message", "integer" ), function(object, field, ...){ .Call( "Message__clear_field", object@pointer, field, PACKAGE = "RProtoBuf" ) invisible( object ) } ) setMethod( "clear", signature( "Message", "numeric" ), function(object, field, ...){ .Call( "Message__clear_field", object@pointer, as.integer(field), PACKAGE = "RProtoBuf" ) invisible( object ) } ) setMethod( "clear", signature( "Message", "raw" ), function(object, field, ...){ .Call( "Message__clear_field", object@pointer, as.integer(field), PACKAGE = "RProtoBuf" ) invisible( object ) } ) RProtoBuf/R/swap.R0000644000176200001440000000067013005133352013430 0ustar liggesuserssetGeneric("swap", function( object, field, left, right) { standardGeneric( "swap" ) } ) setMethod( "swap", "Message", function( object, field, left, right ){ left <- as.integer( left ) - 1L right <- as.integer( right ) - 1L if( length(left) != length(right) ){ stop( "left and right should have the same length" ) } .Call( "Message__swap", object@pointer, field, left, right, PACKAGE = "RProtoBuf" ) invisible( object ) } ) RProtoBuf/R/has.R0000644000176200001440000000105713144043463013240 0ustar liggesusers setGeneric( "has", function( object, name, ... ){ standardGeneric( "has" ) } ) ._has_message <- function( object, name, ...){ if (!.Call( "Message__field_exists", object@pointer, name, PACKAGE = "RProtoBuf" )) { return(NULL) } else { return(.Call( "Message__has_field", object@pointer, name, PACKAGE = "RProtoBuf" )) } } ._has_enum_name <- function( object, name, ...){ return(.Call( "has_enum_name", object@pointer, name, PACKAGE = "RProtoBuf")) } setMethod( "has", "Message", ._has_message ) setMethod( "has", "EnumDescriptor", ._has_enum_name) RProtoBuf/R/extensions.R0000644000176200001440000000375613144043463014674 0ustar liggesusers# Copyright 2012 Google Inc. All Rights Reserved. # Author: mstokely@google.com (Murray Stokely) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301, USA. setGeneric( "setExtension", function(object, field, values){ standardGeneric( "setExtension" ) } ) setMethod( "setExtension", "Message", function( object, field, values ){ if (!inherits(field, "FieldDescriptor")) { stop("setExtension requires a FieldDescriptor") } if (!is_extension(field)) { stop(paste(name(field), "is not an extension FieldDescriptor.")) } .Call( "setMessageField", object@pointer, field, values, PACKAGE = "RProtoBuf" ) invisible( object ) } ) setGeneric( "getExtension", function(object, field){ standardGeneric( "getExtension" ) } ) setMethod( "getExtension", "Message", function( object, field){ if (!inherits(field, "FieldDescriptor")) { stop("getExtension requires a FieldDescriptor") } if (!is_extension(field)) { stop(paste(name(field), "is not an extension FieldDescriptor.")) } # This check causes a CHECK failure in the C++ code, so give # a more user-friendly error here. if (containing_type(field)@type != object@type) { stop(paste("Field", name(field), "does not match message type (", containing_type(field)@type, "!=", object@type, ")")) } .Call( "getExtension_cpp", object@pointer, field, PACKAGE = "RProtoBuf" ) } ) RProtoBuf/R/http.handler.R0000644000176200001440000000103113005133352015041 0ustar liggesusers RProtoBuf.http.handler <- function(path, query, body) { if( !all( c("service", "method" ) %in% names(query) ) ){ stop( "need service and method " ) } service <- query[["service"]] method <- query[["method"]] m <- get( sprintf( "%s.%s", service, method ), as.environment( "RProtoBuf:DescriptorPool" ) ) if( is.null( m ) ){ stop( "unknown method" ) } input <- if( length( body ) ){ m$input_type()$read( body ) } else{ new( m$input_type() ) } res <- invoke( m, input ) list( serialize( res, NULL ) ) } RProtoBuf/R/size.R0000644000176200001440000000203313005133352013423 0ustar liggesusers setGeneric( "bytesize", function(object, ...){ standardGeneric( "bytesize" ) } ) setMethod( "bytesize", "Message", function(object, ...){ .Call( "Message__bytesize", object@pointer, PACKAGE = "RProtoBuf" ) } ) setGeneric( "size", function( object, field, ... ){ standardGeneric( "size" ) } ) setMethod( "size", "Message", function(object, field, ...){ if( is.character( field ) || is.numeric( field ) ){ .Call( "Message__field_size", object@pointer, field, PACKAGE = "RProtoBuf" ) } else{ stop( "field should be a character or a number" ) } } ) setGeneric( "size<-", function( object, field, ..., value ){ standardGeneric( "size<-" ) } ) setMethod( "size<-", "Message", function(object, field, ..., value){ if( !is.numeric( value ) ){ stop("value should be a number") } value <- as.integer( value )[1] if( is.character( field ) || is.numeric( field ) ){ .Call( "Message__set_field_size", object@pointer, field, value, PACKAGE = "RProtoBuf" ) } else{ stop( "field should be a character or a number" ) } object } ) RProtoBuf/R/clone.R0000644000176200001440000000043213144043463013561 0ustar liggesusers setGeneric( "clone", function( object, ... ){ standardGeneric( "clone" ) } ) ._clone.message <- function( object, ... ){ message <- .Call( "Message__clone", object@pointer, PACKAGE="RProtoBuf") update( message, ... ) message } setMethod( "clone", "Message", ._clone.message ) RProtoBuf/R/descriptor.R0000644000176200001440000000233313005133352014632 0ustar liggesusers setGeneric( "descriptor", function(object, ...){ standardGeneric( "descriptor" ) } ) setMethod( "descriptor", "Message", function(object, ...){ .Call( "Message__descriptor", object@pointer, PACKAGE = "RProtoBuf" ) } ) setGeneric( "fileDescriptor", function(object, ...){ standardGeneric( "fileDescriptor" ) } ) setMethod( "fileDescriptor", "Message", function(object, ...){ .Call( "Message__fileDescriptor", object@pointer, PACKAGE = "RProtoBuf" ) } ) setMethod( "fileDescriptor", "Descriptor", function(object, ...){ .Call( "Descriptor__fileDescriptor", object@pointer, PACKAGE = "RProtoBuf" ) } ) setMethod( "fileDescriptor", "EnumDescriptor", function(object, ...){ .Call( "EnumDescriptor__fileDescriptor", object@pointer, PACKAGE = "RProtoBuf" ) } ) setMethod( "fileDescriptor", "FieldDescriptor", function(object, ...){ .Call( "FieldDescriptor__fileDescriptor", object@pointer, PACKAGE = "RProtoBuf" ) } ) setMethod( "fileDescriptor", "ServiceDescriptor", function(object, ...){ .Call( "ServiceDescriptor__fileDescriptor", object@pointer, PACKAGE = "RProtoBuf" ) } ) setMethod( "fileDescriptor", "MethodDescriptor", function(object, ...){ .Call( "MethodDescriptor__fileDescriptor", object@pointer, PACKAGE = "RProtoBuf" ) } ) RProtoBuf/R/internals.R0000644000176200001440000000367213144043463014471 0ustar liggesusers# set of functions not supposed to be called by the end user # these are thin wrappers around C functions, to help with # the error trapping on R side #' thin wrapper around the C function of the same name #' #' @param files list of proto files to import #' @param dir directory in which to look for proto files (ignored if files is given) #' @param package if specified, proto files are imported from the "proto" directory #' of the package #' @return invisible(NULL) readProtoFiles <- function(files, dir, package = "RProtoBuf", pattern = "\\.proto$", lib.loc = NULL ){ if( missing( files ) ){ if( missing( dir ) ){ if( missing(package) ){ dir <- getwd() } else { dir <- system.file( "proto", package = package, lib.loc = lib.loc ) if( !file.exists( dir ) ){ stop( sprintf("package '%s' does not have a 'proto' directory", package) ) } } } files <- list.files( dir, pattern = pattern, full.names = TRUE ) } else { if( !is.character( files ) ){ stop( "'file' should be a character vector" ) } ex <- sapply( files, file.exists ) if( ! any( ex ) ){ stop( "none of the files exist" ) } # TODO: we need to pass the full path of the file # or create a mapping from the current working directory # in the DiskSourceTree files <- sapply(files[ex], function(x) file_path_as_absolute(x) ) } directories <- unique( c( getwd(), dirname(files) ) ) .Call( "readProtoFiles_cpp", files, directories, PACKAGE = "RProtoBuf" ) invisible(NULL) } getProtobufLibVersion <- function( format = FALSE ){ version <- .Call( "get_protobuf_library_version", PACKAGE = "RProtoBuf" ) if( format ){ major <- version %/% 10^6 minor <- ( tmp <- (version - major * 10^6) ) %/% 10^3 revision <- (tmp - minor * 10^3 ) sprintf( "%d.%d.%d", major, minor, revision ) } else { version } } RProtoBuf/R/00classes.R0000644000176200001440000004700013144106760014260 0ustar liggesusers# :tabSize=4:indentSize=4:noTabs=false:folding=explicit:collapseFolds=1: # this has to be IMPLEMENTATIONS <- new.env( parent = emptyenv() ) # invisible version of .Call #.icall <- function(...) invisible(.Call(...)) # {{{ class definitions # we need to formalize connection so that the S4 methods # ConnectionInputStream and ConnectionOutputStream can # dispatch connections setOldClass( "connection" ) # FIXME: there is probably another way # TODO: include other subclasses of connections setOldClass( c("file", "connection" ) ) setOldClass( c("url", "connection" ) ) setClass( "Descriptor", representation( pointer = "externalptr", # pointer to a google::protobuf::Descriptor c++ object type = "character" # message type ), prototype = list( pointer = NULL, type = character(0) ) ) setClass( "FieldDescriptor", representation( pointer = "externalptr" , # pointer to a google::protobuf::FieldDescriptor c++ object name = "character", full_name = "character", type = "character" ), prototype = list( pointer = NULL, name = character(0), full_name = character(0), type = character(0) ) ) setClass( "EnumDescriptor", representation( pointer = "externalptr" , # pointer to a google::protobuf::EnumDescriptor c++ object name = "character", full_name = "character", type = "character" # TODO(mstokely): enums don't really have another type, remove? ), prototype = list( pointer = NULL, name = character(0), full_name = character(0), type = character(0) ) ) setClass( "ServiceDescriptor", representation( pointer = "externalptr", # pointer to a google::protobuf::ServiceDescriptor c++ object name = "character" # full name of the service ), prototype = list( pointer = NULL, name = character(0) ) ) setClass( "MethodDescriptor", representation( pointer = "externalptr", # pointer to a google::protobuf::ServiceDescriptor c++ object name = "character" , # full name of the service service = "character" # full name of the service that defines this method ), prototype = list( pointer = NULL, name = character(0), service = character(0) ) ) setClass( "FileDescriptor", representation( pointer = "externalptr", # pointer to a google::protobuf::FileDescriptor c++ object filename = "character", # filename package = "character" # the package ), prototype = list( pointer = NULL, filename = character(0), package = character(0) ) ) setClass( "EnumValueDescriptor", representation( pointer = "externalptr", # pointer to a google::protobuf::EnumValueDescriptor c++ object name = "character", full_name = "character" ), prototype = list( pointer = NULL, name = character(0), full_name = character(0) ) ) # actual objects setClass( "Message", representation( pointer = "externalptr", # pointer to sa google::protobuf::Message object type = "character" # message type (fully qualified, with package path) ), prototype = list( pointer = NULL, type = character(0) ) ) # rpc setClass( "RpcHTTP", representation( host = "character", port = "integer", root = "character" ), prototype = list( host = "127.0.0.1", port = 4444L, root = "" ) ) # streams setClass( "ZeroCopyInputStream", representation( pointer = "externalptr" ), prototype = list( pointer = NULL ), contains = "VIRTUAL" ) setClass( "ArrayInputStream", contains = "ZeroCopyInputStream" ) setClass( "FileInputStream", contains = "ZeroCopyInputStream" ) setClass( "ConnectionInputStream", contains = "ZeroCopyInputStream" ) setClass( "ZeroCopyOutputStream", representation( pointer = "externalptr" ), prototype = list( pointer = NULL ), contains = "VIRTUAL" ) setClass( "ArrayOutputStream", contains = "ZeroCopyInputStream" ) setClass( "FileOutputStream", contains = "ZeroCopyInputStream" ) setClass( "ConnectionOutputStream", contains = "ZeroCopyOutputStream" ) # }}} # {{{ new newProto <- function( descriptor, ... ){ message <- .Call( "newProtoMessage", descriptor, PACKAGE = "RProtoBuf" ) update( message, ... ) message } setGeneric("new") setMethod("new", signature(Class="Descriptor"), function(Class, ...) newProto(Class, ...)) # }}} # {{{ P P <- function( type, file ){ if( !missing(file) ){ readProtoFiles( file ) } if( missing( type ) ){ stop( "'type' is required" ) } if( !is.character(type) ){ stop( "'type' is not a character vector" ) } if( length(type) != 1L){ stop( "'type' should have exactly one element" ) } desc <- .Call( "getProtobufDescriptor", type, PACKAGE = "RProtoBuf" ) if( is.null( desc ) ){ # See if it is an extension desc <- .Call("getExtensionDescriptor", type, PACKAGE="RProtoBuf") if (is.null(desc)) { # See if it is an enum desc <- .Call("getEnumDescriptor", type, PACKAGE="RProtoBuf") if (is.null(desc)) { stop( sprintf( "could not find descriptor for message type '%s' ", type ) ) } } } desc } # }}} # {{{ show setMethod( "show", c( "Message" ), function(object){ tmp <- sprintf( "message of type '%s' with %d field%s set", object@type, length(object), if (length(object) == 1) "" else "s" ) nexts <- .Call("Message__num_extensions", object@pointer, PACKAGE="RProtoBuf") if (nexts > 0) { tmp <- paste(tmp, sprintf("and %d extension%s", nexts, if (nexts == 1) "" else "s")) } cat(tmp, fill=TRUE) } ) setMethod( "show", c( "Descriptor" ), function(object){ cat( sprintf( "descriptor for type '%s' ", object@type ) , fill=TRUE) } ) setMethod( "show", c( "FieldDescriptor" ), function(object){ cat( sprintf( "descriptor for field '%s' of type '%s' ", object@name, object@type ), fill=TRUE) } ) setMethod( "show", c( "EnumDescriptor" ), function(object){ cat( sprintf( "descriptor for enum '%s' with %d values", object@name, value_count(object) ) , fill=TRUE) } ) setMethod( "show", c( "ServiceDescriptor" ), function(object){ cat( sprintf( "service descriptor <%s>", object@name ) , fill=TRUE) } ) setMethod( "show", c( "FileDescriptor" ), function(object){ cat( sprintf( "file descriptor for package %s (%s)", object@package, object@filename) , fill=TRUE) } ) setMethod( "show", c( "EnumValueDescriptor" ), function(object){ cat( sprintf( "enum value descriptor %s", object@full_name), fill=TRUE) } ) # }}} # {{{ dollar extractors setMethod("$", "Message", function(x, name) { switch( name, "has" = function( ... ) has(x, ...), "clone" = function( ... ) .Call( "Message__clone" , x@pointer, PACKAGE = "RProtoBuf"), "isInitialized" = function() .Call( "Message__is_initialized", x@pointer, PACKAGE = "RProtoBuf"), "descriptor" = function() .Call( "Message__descriptor" , x@pointer, PACKAGE = "RProtoBuf"), "size" = function(field, ...) size(x, field, ... ), "bytesize" = function() bytesize(x), "swap" = function(...) swap(x,...), "update" = function(...) update(x, ...), "str" = function() str(x), "as.character" = function() as.character(x), "as.list" = function() as.list(x), "asMessage" = function() asMessage(x), "setExtension" = function(field, values, ...) setExtension(x, field, values, ...), "getExtension" = function(field, ...) getExtension(x, field, ...), "set" = function(...) set( x, ... ), "fetch" = function(...) fetch(x, ... ), "toString" = function(...) toString( x, ... ), "add" = function(...) add( x, ...), "serialize" = function(...) serialize( x, ... ), "clear" = function(...) clear( x, ... ), "fileDescriptor" = function() fileDescriptor(x ), # default .Call( "getMessageField", x@pointer, name, PACKAGE = "RProtoBuf" ) ) } ) setMethod("$<-", "Message", function(x, name, value) { .Call( "setMessageField", x@pointer, name, value, PACKAGE = "RProtoBuf" ) x } ) setMethod("$", "Descriptor", function(x, name) { switch( name, "new" = function( ... ) newProto( x, ... ) , "read" = function( input ) read( x, input ) , "readASCII" = function(input, ...) readASCII(x, input, ...), "toString" = function(...) toString(x, ...) , "as.character" = function(...) as.character(x, ...) , "as.list" = function(...) as.list(x, ...) , "asMessage" = function() asMessage(x), "fileDescriptor" = function() fileDescriptor(x ), "name" = function(...) name(x, ... ), "containing_type" = function() containing_type(x), "field_count" = function() field_count(x), "nested_type_count" = function() nested_type_count(x), "enum_type_count" = function() enum_type_count(x), "field" = function(...) field( x, ... ), "nested_type" = function(...) nested_type( x, ...), "enum_type" = function(...) enum_type( x, ...), # default .Call( "do_dollar_Descriptor", x@pointer, name, PACKAGE="RProtoBuf") ) } ) setMethod( "$", "EnumDescriptor", function(x, name ){ switch( name, "as.character" = function() as.character(x), "as.list"= function() as.list(x) , "asMessage" = function() asMessage(x), "toString" = function(...) toString(x, ...) , "name" = function(...) name(x, ...), "fileDescriptor" = function() fileDescriptor(x ), "containing_type" = function() containing_type(x), "length" = function() length(x), "value_count" = function() value_count(x), "value" = function(...) value(x, ...), "has" = function(name, ...) has(x, name, ...), # default .Call( "get_value_of_enum", x@pointer, name, PACKAGE = "RProtoBuf" ) ) } ) setMethod( "$", "FieldDescriptor", function(x, name ){ switch( name, "as.character" = function() as.character(x), "asMessage" = function() asMessage(x), "toString" = function(...) toString(x, ...) , "name" = function(...) name(x, ...), "fileDescriptor" = function() fileDescriptor(x ), "containing_type" = function() containing_type(x), "is_extension" = function() is_extension(x), "number" = function() number(x), "type" = function(...) type(x, ...), "cpp_type" = function(...) cpp_type(x, ...), "label" = function(...) label(x, ...), "is_repeated" = function() is_repeated(x), "is_required" = function() is_required(x), "is_optional" = function() is_optional(x), "has_default_value" = function() has_default_value(x), "default_value" = function() default_value(x), "enum_type" = function() enum_type(x), "message_type" = function() message_type(x), invisible(NULL) ) } ) setMethod( "$", "ServiceDescriptor", function(x, name ){ switch( name, "as.character" = function() as.character(x), "asMessage" = function() asMessage(x), "toString" = function(...) toString(x, ...) , "name" = function(...) name(x, ...), "fileDescriptor" = function() fileDescriptor(x ), "method_count" = function() method_count(x), "method" = function(...) method(x, ... ), .Call( "ServiceDescriptor__method", x@pointer, name, PACKAGE = "RProtoBuf" ) ) } ) setMethod( "$", "FileDescriptor", function(x, name ){ switch( name, "as.character" = function() as.character(x), "toString" = function(...) toString(x, ...) , "asMessage" = function() asMessage(x), "as.list" = function() as.list(x), "name" = function(...) name(x, ... ), "package" = function() x@package, as.list(x)[[name]] ) }) setMethod( "$", "EnumValueDescriptor", function(x, name ){ switch( name, "as.character" = function() as.character(x), "toString" = function(...) toString(x, ...) , "asMessage" = function() asMessage(x), "name" = function(...) name(x, ... ), "number" = function() number(x), "enum_type" = function(...) enum_type( x, ...), invisible(NULL) ) }) setMethod( "$", "MethodDescriptor", function(x, name ){ switch( name, "invoke" = function(...) invoke(x, ...), "implementation" = if( x@name %in% names(IMPLEMENTATIONS) ){ get( x@name, IMPLEMENTATIONS ) }, "name" = function(...) name(x, ...), "toString" = function() toString(x) , "as.character" = function() as.character(x), "fileDescriptor" = function() fileDescriptor(x ), "input_type" = function() input_type(x), "output_type" = function() output_type(x), invisible( NULL) ) } ) setMethod( "$<-", "MethodDescriptor", function(x, name, value ){ if( identical( name, "implementation" ) ){ check_valid_implementation( x, value ) assign( x@name, value, envir = IMPLEMENTATIONS ) } x } ) setMethod( "$", "ZeroCopyInputStream", function(x, name ){ switch( name, # ZeroCopyInputStream C++ methods "Next" = function(...) Next(x, ...), "ByteCount" = function(...) ByteCount(x, ...), "Skip" = function(...) Skip(x, ...), "BackUp" = function(...) BackUp(x, ...), # CodedInputStream related "ReadRaw" = function(...) ReadRaw(x, ...), "ReadString" = function(...) ReadString(x, ...), "ReadVarint32"= function() ReadVarint32(x), "ReadVarint64" = function() ReadVarint64(x), "ReadLittleEndian32" = function() ReadLittleEndian32(x), "ReadLittleEndian64" = function() ReadLittleEndian64(x), # default invisible(NULL) ) } ) setMethod( "$", "ZeroCopyOutputStream", function(x, name ){ switch( name, # ZeroCopyInputStream C++ methods "Next" = function(...) Next(x, ...), "ByteCount" = function(...) ByteCount(x, ...), "BackUp" = function(...) BackUp(x, ...), # CodedOutputStream related "WriteRaw" = function(...) WriteRaw(x, ...), "WriteString" = function(...) WriteString(x, ...), "WriteLittleEndian32" = function(...) WriteLittleEndian32(x,...), "WriteLittleEndian64" = function(...) WriteLittleEndian64(x,...), "WriteVarint32" = function(...) WriteVarint32(x, ...), "WriteVarint64" = function(...) WriteVarint64(x, ...), # default invisible(NULL) ) } ) # }}} # {{{ [[ setMethod( "[[", "Message", function(x, i, j, ..., exact = TRUE){ if( missing( i ) ){ stop( "`i` is required" ) } if( !missing(j) ){ warning( "`j` is ignored" ) } ## This works correctly by number or name. e.g. p[[1]] or p[["name"]] if( is.character( i ) || is.numeric( i ) ){ .Call( "getMessageField", x@pointer, i, PACKAGE = "RProtoBuf" ) } else { stop( "wrong type, `i` should be a character or a number" ) } } ) setMethod( "[[", "Descriptor", function(x, i, j, ..., exact = TRUE){ if( missing( i ) ){ stop( "`i` is required" ) } if( !missing(j) ){ warning( "`j` is ignored" ) } if( is.character( i ) ) { # gets a named field, nested type, or enum. .Call("Descriptor_getField", x@pointer, i, PACKAGE="RProtoBuf") } else if (is.numeric( i ) ) { return(as.list(x)[[i]]) } else { stop( "wrong type, `i` should be a character or a number" ) } } ) setMethod( "[[", "EnumDescriptor", function(x, i, j, ..., exact = TRUE){ if( missing( i ) ){ stop( "`i` is required" ) } if( !missing(j) ){ warning( "`j` is ignored" ) } if (is.character(i) || is.numeric(i)) { return(as.list(x)[[i]]) } else { stop( "wrong type, `i` should be a character or a number" ) } } ) setMethod("[[", "ServiceDescriptor", function(x, i, j, ..., exact = TRUE){ if( missing( i ) ){ stop( "`i` is required" ) } if( !missing(j) ){ warning( "`j` is ignored" ) } if( is.character( i ) || is.numeric( i ) ){ .Call( "ServiceDescriptor__method", x@pointer, name, PACKAGE = "RProtoBuf" ) } else{ stop( "wrong type, `i` should be a character or a number" ) } } ) # }}} # {{{ [[<- setReplaceMethod( "[[", "Message", function(x, i, j, ..., exact = TRUE, value ){ # TODO: we might want to relax this later, i.e # allow to mutate repeated fields like this: # x[[ "field", 1:2 ]] <- 1:2 if( missing( i ) ){ stop( "`i` is required" ) } if( !missing(j) ){ warning( "`j` is ignored" ) } if( is.character( i ) || is.numeric( i ) ){ .Call( "setMessageField", x@pointer, i, value, PACKAGE = "RProtoBuf" ) } else { stop( "wrong type, `i` should be a character or a number" ) } x } ) # }}} # {{{ update setGeneric( "update" ) setMethod( "update", "Message", function( object, ... ){ dots <- list( ... ) if( !length( dots ) ){ return( object ) } names <- names( dots ) named <- dots[ names != "" ] if( !length( named ) ){ return( object ) } .Call( "update_message", object@pointer, named, PACKAGE="RProtoBuf") object } ) # }}} # {{{ length setGeneric( "length" ) setMethod( "length", "Message", function( x ){ .Call( "Message__length", x@pointer, PACKAGE = "RProtoBuf" ) } ) # Returns number of fields, enums, types in message descriptor. # May be more than field_count which is only fields. # e.g. length(tutorial.Person) > field_count(tutorial.Person) setMethod( "length", "Descriptor", function( x ){ length(as.list(x)) } ) setMethod( "length", "EnumDescriptor", function( x ){ .Call( "EnumDescriptor__length", x@pointer, PACKAGE = "RProtoBuf" ) } ) setMethod( "length", "ServiceDescriptor", function( x ){ .Call( "ServiceDescriptor_method_count", x@pointer, PACKAGE = "RProtoBuf" ) } ) # }}} # {{{ str # we need to do this otherwise it gets messed up by the length method setGeneric( "str" ) setMethod( "str", "Message", function( object, ...){ txt <- sprintf( ' Formal class \'Message\' [package "RProtoBuf"] with 2 slots ..@ pointer: ..@ type : chr "%s" ', object@type ) writeLines( txt ) } ) # }}} # {{{ name setGeneric( "name", function(object, full = FALSE){ standardGeneric( "name" ) }) setMethod( "name", c( object = "Descriptor" ) , function(object, full = FALSE){ .Call( "Descriptor__name", object@pointer, full, PACKAGE = "RProtoBuf" ) }) setMethod( "name", c( object = "FieldDescriptor" ) , function(object, full = FALSE){ .Call( "FieldDescriptor__name", object@pointer, full, PACKAGE = "RProtoBuf" ) }) setMethod( "name", c( object = "EnumDescriptor" ) , function(object, full = FALSE){ .Call( "EnumDescriptor__name", object@pointer, full, PACKAGE = "RProtoBuf" ) }) setMethod( "name", c( object = "EnumValueDescriptor" ) , function(object, full = FALSE){ .Call( "EnumDescriptor__name", object@pointer, full, PACKAGE = "RProtoBuf" ) }) setMethod( "name", c( object = "ServiceDescriptor" ) , function(object, full = FALSE){ .Call( "ServiceDescriptor__name", object@pointer, full, PACKAGE = "RProtoBuf" ) }) setMethod( "name", c( object = "MethodDescriptor" ) , function(object, full = FALSE){ .Call( "MethodDescriptor__name", object@pointer, full, PACKAGE = "RProtoBuf" ) }) setMethod( "name", c( object = "FileDescriptor" ) , function(object, full = FALSE){ filename <- .Call( "FileDescriptor__name", object@pointer, PACKAGE = "RProtoBuf" ) if( full ) filename else basename( filename ) }) # }}} # {{{ names # as.list() and names() don't make as much sense for FieldDescriptors, # EnumValueDescriptors, etc. setMethod( "names", c( x = "Message" ) , function(x){ names(as.list(x)) }) setMethod( "names", c( x = "Descriptor" ) , function(x){ names(as.list(x)) }) setMethod( "names", c( x = "EnumDescriptor" ) , function(x){ names(as.list(x)) }) # }}} # {{{ as setAs("Descriptor", "Message", function(from){ .Call( "Descriptor__as_Message", from@pointer, PACKAGE = "RProtoBuf" ) }) setAs("FieldDescriptor", "Message", function(from){ .Call( "FieldDescriptor__as_Message", from@pointer, PACKAGE = "RProtoBuf" ) }) setAs("EnumDescriptor", "Message", function(from){ .Call( "EnumDescriptor__as_Message", from@pointer, PACKAGE = "RProtoBuf" ) }) setAs("ServiceDescriptor", "Message", function(from){ .Call( "ServiceDescriptor__as_Message", from@pointer, PACKAGE = "RProtoBuf" ) }) setAs("MethodDescriptor", "Message", function(from){ .Call( "MethodDescriptor__as_Message", from@pointer, PACKAGE = "RProtoBuf" ) }) setAs("FileDescriptor", "Message", function(from){ .Call( "FileDescriptor__as_Message", from@pointer, PACKAGE = "RProtoBuf" ) }) setAs("EnumValueDescriptor", "Message", function(from){ .Call( "EnumValueDescriptor__as_Message", from@pointer, PACKAGE = "RProtoBuf" ) }) asMessage <- function( x, ... ){ as( x, "Message", ... ) } # }}} # {{{ enum_type setGeneric( "enum_type", function( object, index, name ){ standardGeneric( "enum_type" ) }) # }}} RProtoBuf/R/completion.R0000644000176200001440000000763313005133352014635 0ustar liggesusers# :tabSize=4:indentSize=4:noTabs=false:folding=explicit:collapseFolds=1: # implementation of completion for proto messages # through the .DollarNames method (R>= 2.10.0) # S4 dispatch does not work for .DollarNames, so we'll use S3 # {{{ bring .DollarNames from the future if necessary if( !exists( ".DollarNames", envir = asNamespace("utils") ) ){ .DollarNames <- function(x, pattern) UseMethod(".DollarNames") } # }}} # {{{ Message .DollarNames.Message <- function(x, pattern = "" ){ names <- c( .Call( "Message__fieldNames", x@pointer, PACKAGE = "RProtoBuf" ) , "has(", "clone()", "clone(", "isInitialized()", "serialize(", "clear()", "clear(", "size(", "bytesize()", "fetch(", "swap(", "str()", "as.character()", "update(", "as.list()", "setExtension(", "getExtension(", "descriptor()", "set(", "toString(", "add(", "fileDescriptor()" ) grep( pattern, names, value = TRUE ) } # }}} # {{{ Descriptor .DollarNames.Descriptor <- function(x, pattern = "" ){ names <- c( .Call( "Descriptor__getMemberNames", x@pointer, PACKAGE = "RProtoBuf" ), "new(", "read(", "readASCII(", "fileDescriptor()", "name(", "toString()", "as.character()", "asMessage()", "containing_type()", "field_count()", "nested_type_count()", "enum_type_count", "field(", "nested_type(", "enum_type(" ) grep( pattern, names, value = TRUE ) } # }}} # {{{ EnumDescriptor .DollarNames.EnumDescriptor <- function(x, pattern = "" ){ names <- c( .Call( "EnumDescriptor__getConstantNames", x@pointer, PACKAGE = "RProtoBuf" ), "name(", "fileDescriptor()", "as.character()", "toString()", "containing_type()", "length()", "value_count()", "value(", "has(", "asMessage()") grep( pattern, names, value = TRUE ) } # }}} # {{{ EnumValueDescriptor .DollarNames.EnumValueDescriptor <- function(x, pattern = "" ){ names <- c("number()", "name()", "enum_type()", "as.character()", "toString()", "asMessage()") grep( pattern, names, value = TRUE ) } # }}} # {{{ FieldDescriptor .DollarNames.FieldDescriptor <- function(x, pattern = "" ){ names <- c("as.character()", "toString()", "name(", "fileDescriptor()", "containing_type()", "is_extension()", "number()", "type(", "cpp_type(", "label(", "is_repeated()", "is_required()", "is_optional()", "message_type()", "enum_type()", "asMessage()", "has_default_value()", "default_value(" ) grep( pattern, names, value = TRUE ) } # }}} # {{{ ServiceDescriptor .DollarNames.ServiceDescriptor <- function(x, pattern = "" ){ names <- c( .Call( "ServiceDescriptor__getMethodNames", x@pointer, PACKAGE = "RProtoBuf" ), "as.character()", "toString()", "name(", "fileDescriptor()", "method_count()", "method(name=", "method(index=" ) grep( pattern, names, value = TRUE ) } # }}} # {{{ MethodDescriptor .DollarNames.MethodDescriptor <- function(x, pattern = "" ){ names <- c("as.character()", "toString()", "name(", "fileDescriptor()", "input_type()", "output_type()" ) grep( pattern, names, value = TRUE ) } # }}} # {{{ FileDescriptor .DollarNames.FileDescriptor <- function(x, pattern = "" ){ names <- c( .Call( "FileDescriptor__getMemberNames", x@pointer, PACKAGE = "RProtoBuf" ), "as.character()", "toString()", "name(", "as.list()", "asMessage()", "package()") grep( pattern, names, value = TRUE ) } # }}} # {{{ ZeroCopyInputStream .DollarNames.ZeroCopyInputStream <- function(x, pattern = "" ){ names <- c("Next()", "ByteCount()", "Skip(", "BackUp(", "ReadRaw(", "ReadString()", "ReadVarint32()", "ReadVarint64()", "ReadLittleEndian32()", "ReadLittleEndian64()" ) grep( pattern, names, value = TRUE ) } # }}} # {{{ ZeroCopyOutputStream .DollarNames.ZeroCopyOutputStream <- function(x, pattern = "" ){ names <- c("Next(", "ByteCount()", "BackUp(", "WriteRaw(", "WriteString(", "WriteLittleEndian32(", "WriteLittleEndian64(", "WriteVarint32(", "WriteVarint64(" ) grep( pattern, names, value = TRUE ) } # }}} RProtoBuf/R/unit_tests.R0000644000176200001440000000017713144043463014670 0ustar liggesusers run_unit_tests <- function(){ script <- system.file( "unitTests", "runTests.R", package = "RProtoBuf" ) source( script ) } RProtoBuf/R/wrapper_CodedOutputStream.R0000644000176200001440000000702413005133352017631 0ustar liggesuserssetGeneric( "WriteRaw", function(object, payload){ standardGeneric("WriteRaw") } ) setMethod( "WriteRaw", c(object="ZeroCopyOutputStream", payload = "raw" ), function(object, payload){ .Call( "ZeroCopyOutputStream_WriteRaw", object@pointer, payload, PACKAGE = "RProtoBuf" ) } ) setGeneric( "WriteString", function(object, payload){ standardGeneric("WriteString") } ) setMethod( "WriteString", c(object="ZeroCopyOutputStream", payload = "character" ), function(object, payload){ .Call( "ZeroCopyOutputStream_WriteString", object@pointer, payload, PACKAGE = "RProtoBuf" ) } ) setGeneric( "WriteLittleEndian32", function(object, payload){ standardGeneric("WriteLittleEndian32") } ) setMethod( "WriteLittleEndian32", c(object="ZeroCopyOutputStream", payload = "integer" ), function(object, payload){ .Call( "ZeroCopyOutputStream_WriteLittleEndian32", object@pointer, payload, PACKAGE = "RProtoBuf" ) } ) setMethod( "WriteLittleEndian32", c(object="ZeroCopyOutputStream", payload = "numeric" ), function(object, payload){ .Call( "ZeroCopyOutputStream_WriteLittleEndian32", object@pointer, payload, PACKAGE = "RProtoBuf" ) } ) setMethod( "WriteLittleEndian32", c(object="ZeroCopyOutputStream", payload = "raw" ), function(object, payload){ .Call( "ZeroCopyOutputStream_WriteLittleEndian32", object@pointer, payload, PACKAGE = "RProtoBuf" ) } ) setGeneric( "WriteLittleEndian64", function(object, payload){ standardGeneric("WriteLittleEndian64") } ) setMethod( "WriteLittleEndian64", c(object="ZeroCopyOutputStream", payload = "integer" ), function(object, payload){ .Call( "ZeroCopyOutputStream_WriteLittleEndian64", object@pointer, payload, PACKAGE = "RProtoBuf" ) } ) setMethod( "WriteLittleEndian64", c(object="ZeroCopyOutputStream", payload = "numeric" ), function(object, payload){ .Call( "ZeroCopyOutputStream_WriteLittleEndian64", object@pointer, payload, PACKAGE = "RProtoBuf" ) } ) setMethod( "WriteLittleEndian64", c(object="ZeroCopyOutputStream", payload = "raw" ), function(object, payload){ .Call( "ZeroCopyOutputStream_WriteLittleEndian64", object@pointer, payload, PACKAGE = "RProtoBuf" ) } ) setGeneric( "WriteVarint32", function(object, payload){ standardGeneric("WriteVarint32") } ) setMethod( "WriteVarint32", c(object="ZeroCopyOutputStream", payload = "integer" ), function(object, payload){ .Call( "ZeroCopyOutputStream_WriteVarint32", object@pointer, payload, PACKAGE = "RProtoBuf" ) } ) setMethod( "WriteVarint32", c(object="ZeroCopyOutputStream", payload = "numeric" ), function(object, payload){ .Call( "ZeroCopyOutputStream_WriteVarint32", object@pointer, payload, PACKAGE = "RProtoBuf" ) } ) setMethod( "WriteVarint32", c(object="ZeroCopyOutputStream", payload = "raw" ), function(object, payload){ .Call( "ZeroCopyOutputStream_WriteVarint32", object@pointer, payload, PACKAGE = "RProtoBuf" ) } ) setGeneric( "WriteVarint64", function(object, payload){ standardGeneric("WriteVarint64") } ) setMethod( "WriteVarint64", c(object="ZeroCopyOutputStream", payload = "integer" ), function(object, payload){ .Call( "ZeroCopyOutputStream_WriteVarint64", object@pointer, payload, PACKAGE = "RProtoBuf" ) } ) setMethod( "WriteVarint64", c(object="ZeroCopyOutputStream", payload = "numeric" ), function(object, payload){ .Call( "ZeroCopyOutputStream_WriteVarint64", object@pointer, payload, PACKAGE = "RProtoBuf" ) } ) setMethod( "WriteVarint64", c(object="ZeroCopyOutputStream", payload = "raw" ), function(object, payload){ .Call( "ZeroCopyOutputStream_WriteVarint64", object@pointer, payload, PACKAGE = "RProtoBuf" ) } ) RProtoBuf/R/rexp_obj.R0000644000176200001440000001021413144043463014270 0ustar liggesusers# Functions to convert an arbitrary R object into a protocol buffer # using the universal rexp.proto descriptor. # # Written by Jeroen Ooms # Modified 2014 by Murray Stokely to support language and environment types rexp_obj <- function(obj){ if(isS4(obj)) { # Some S4 objects do not return "S4" from typeof. e.g. lubridate interval # These must be natively encoded or we will lose the S4 flag. return(rexp_native(obj)) } sm <- typeof(obj); msg <- switch(sm, "character" = rexp_string(obj), "raw" = rexp_raw(obj), "double" = rexp_double(obj), "complex" = rexp_complex(obj), "integer" = rexp_integer(obj), "list" = rexp_list(obj), "logical" = rexp_logical(obj), "NULL" = rexp_null(), return(rexp_native(obj)) ); attrib <- attributes(obj) msg$attrName <- names(attrib) msg$attrValue <- lapply(attrib, rexp_obj) msg } rexp_string <- function(obj){ xvalue <- lapply(as.list(obj), function(x){ new(pb(rexp.STRING), strval=x, isNA=is.na(x)) }) new(pb(rexp.REXP), rclass = 0, stringValue=xvalue) } # For objects that only make sense in R, we just fall back # to R's default serialization. rexp_native <- function(obj){ new(pb(rexp.REXP), rclass= 8, nativeValue = base::serialize(obj, NULL)) } rexp_raw <- function(obj){ new(pb(rexp.REXP), rclass= 1, rawValue = obj) } rexp_double <- function(obj){ new(pb(rexp.REXP), rclass=2, realValue = obj) } rexp_complex <- function(obj){ xvalue <- lapply(as.list(obj), function(x){ new(pb(rexp.CMPLX), real=Re(x), imag=Im(x)) }) new(pb(rexp.REXP), rclass=3, complexValue = xvalue) } rexp_integer <- function(obj){ new(pb(rexp.REXP), rclass=4, intValue = obj) } rexp_list <- function(obj){ xobj <- lapply(obj, rexp_obj) new(pb(rexp.REXP), rclass=5, rexpValue = xobj) } rexp_logical <- function(obj){ xobj <- as.integer(obj) xobj[is.na(obj)] <- 2 new(pb(rexp.REXP), rclass=6, booleanValue = xobj) } rexp_null <- function(){ new(pb(rexp.REXP), rclass=7) } unrexp <- function(msg){ stopifnot(is(msg, "Message")) stopifnot(msg@type == "rexp.REXP") myrexp <- as.list(msg) xobj <- switch(as.character(myrexp$rclass), "0" = unrexp_string(myrexp), "1" = unrexp_raw(myrexp), "2" = unrexp_double(myrexp), "3" = unrexp_complex(myrexp), "4" = unrexp_integer(myrexp), "5" = unrexp_list(myrexp), "6" = unrexp_logical(myrexp), "7" = unrexp_null(), "8" = unrexp_native(myrexp), stop("Unsupported rclass:", myrexp$rclass) ) if(length(myrexp$attrValue)){ attrib <- lapply(myrexp$attrValue, unrexp) names(attrib) <- myrexp$attrName tryCatch(attributes(xobj) <- attrib, error=function(cond) { #Try not setting the class in case the values are invalid attributes(xobj) <- attrib[names(attrib)!="class"] warning("Unable to set class, ", cond$message) }) } xobj } unrexp_string <- function(myrexp){ mystring <- unlist(lapply(myrexp$stringValue, "[[", "strval")) isNA <- unlist(lapply(myrexp$stringValue, "[[", "isNA")) mystring[isNA] <- NA as.character(mystring) } unrexp_raw <- function(myrexp){ myrexp$rawValue } unrexp_double <- function(myrexp){ myrexp$realValue } unrexp_complex <- function(myrexp){ xvalue <- lapply(myrexp$complexValue, function(x){ complex(real=x$real, imaginary=x$imag) }) as.complex(unlist(xvalue)) } unrexp_integer <- function(myrexp){ myrexp$intValue } unrexp_list <- function(myrexp){ lapply(myrexp$rexpValue, unrexp) } unrexp_logical <- function(myrexp){ xvalue <- myrexp$booleanValue xvalue[xvalue==2] <- NA as.logical(xvalue) } unrexp_null <- function(){ NULL } unrexp_native <- function(myrexp){ buf <- myrexp$nativeValue if(!length(buf)) return(NULL) unserialize(buf) } #Helper function to lookup a PB descriptor pb <- function(name){ descriptor <- deparse(substitute(name)) if(!exists(descriptor, "RProtoBuf:DescriptorPool")){ stop("No ProtoBuf Descriptor for: ", descriptor) } get(descriptor, "RProtoBuf:DescriptorPool") } #Checks if object can be serialized can_serialize_pb <- rexp_valid <- function(obj) { # We can now serialize everything. just call back to R serialization return(TRUE) } RProtoBuf/R/wrapper_ZeroCopyInputStream.R0000644000176200001440000001634513005133352020172 0ustar liggesusers# :tabSize=4:indentSize=4:noTabs=false:folding=explicit:collapseFolds=1: # {{{ generics setGeneric( "flush" ) setGeneric( "close" ) setGeneric( "GetErrno", function(object){ standardGeneric( "GetErrno" ) } ) setGeneric( "SetCloseOnDelete", function(object, close=FALSE){ standardGeneric( "SetCloseOnDelete" ) } ) # }}} # {{{ methods setGeneric( "Next", function(object, payload){ standardGeneric( "Next" ) } ) setGeneric( "BackUp", function(object, count){ standardGeneric( "BackUp" ) } ) setGeneric( "ByteCount", function(object){ standardGeneric( "ByteCount" ) } ) setGeneric( "Skip", function(object, count){ standardGeneric( "Skip" ) } ) # }}} # {{{ zero input stream setMethod( "Next", c( object = "ZeroCopyInputStream", payload = "missing"), function(object, payload){ .Call( "ZeroCopyInputStream_Next", object@pointer, PACKAGE = "RProtoBuf" ) } ) setMethod( "BackUp", "ZeroCopyInputStream", function(object, count){ invisible(.Call( "ZeroCopyInputStream_BackUp", object@pointer, count, PACKAGE = "RProtoBuf" )) } ) setMethod( "ByteCount", "ZeroCopyInputStream", function(object){ .Call( "ZeroCopyInputStream_ByteCount", object@pointer, PACKAGE = "RProtoBuf" ) } ) setMethod( "Skip", "ZeroCopyInputStream", function(object, count){ invisible( .Call( "ZeroCopyInputStream_Skip", object@pointer, count, PACKAGE = "RProtoBuf" ) ) } ) # }}} # {{{ zero copy output stream setMethod( "Next", c( object = "ZeroCopyOutputStream", payload = "raw" ), function(object, payload){ .Call( "ZeroCopyOutputStream_Next", object@pointer, payload, PACKAGE = "RProtoBuf" ) } ) setMethod( "BackUp", "ZeroCopyOutputStream", function(object, count){ invisible( .Call( "ZeroCopyOutputStream_BackUp", object@pointer, count, PACKAGE = "RProtoBuf" ) ) } ) setMethod( "ByteCount", "ZeroCopyOutputStream", function(object){ .Call( "ZeroCopyOutputStream_ByteCount", object@pointer, PACKAGE = "RProtoBuf" ) } ) # }}} # {{{ ArrayInputStream setGeneric( "ArrayInputStream", function(payload, block_size){ standardGeneric( "ArrayInputStream" ) } ) setMethod( "ArrayInputStream", c( payload = "raw", block_size = "missing" ) , function(payload, block_size){ .Call( "ArrayInputStream__new", payload, -1L, PACKAGE = "RProtoBuf" ) } ) setMethod( "ArrayInputStream", c( payload = "raw", block_size = "integer" ) , function(payload, block_size){ .Call( "ArrayInputStream__new", payload, block_size, PACKAGE = "RProtoBuf" ) } ) setMethod( "ArrayInputStream", c( payload = "raw", block_size = "numeric" ) , function(payload, block_size){ .Call( "ArrayInputStream__new", payload, as.integer(block_size), PACKAGE = "RProtoBuf" ) } ) # }}} # {{{ ArrayOutputStream constructor function setGeneric( "ArrayOutputStream", function(size, block_size){ standardGeneric( "ArrayOutputStream" ) } ) setMethod( "ArrayOutputStream", signature( size = "integer", block_size = "missing" ), function(size, block_size){ .Call( "ArrayOutputStream__new", size, -1L, PACKAGE = "RProtoBuf" ) } ) setMethod( "ArrayOutputStream", signature( size = "integer", block_size = "integer" ), function(size, block_size){ .Call( "ArrayOutputStream__new", size, block_size, PACKAGE = "RProtoBuf" ) } ) setMethod( "ArrayOutputStream", signature( size = "integer", block_size = "numeric" ), function(size, block_size){ .Call( "ArrayOutputStream__new", size, as.integer(block_size) , PACKAGE = "RProtoBuf" ) } ) setMethod( "ArrayOutputStream", signature( size = "numeric", block_size = "missing" ), function(size, block_size){ .Call( "ArrayOutputStream__new", as.integer(size), -1L, PACKAGE = "RProtoBuf" ) } ) setMethod( "ArrayOutputStream", signature( size = "numeric", block_size = "integer" ),function(size, block_size){ .Call( "ArrayOutputStream__new", as.integer(size), block_size, PACKAGE = "RProtoBuf" ) } ) setMethod( "ArrayOutputStream", signature( size = "numeric", block_size = "numeric" ), function(size, block_size){ .Call( "ArrayOutputStream__new", as.integer(size), as.integer(block_size) , PACKAGE = "RProtoBuf" ) } ) # }}} # {{{ FileInputStream setGeneric( "FileInputStream", function(filename, block_size = -1L, close.on.delete = FALSE ){ standardGeneric( "FileInputStream" ) } ) setMethod( "FileInputStream", signature( filename = "character", block_size = "integer", close.on.delete = "logical" ), function(filename, block_size = -1L, close.on.delete = FALSE){ full_filename <- file_path_as_absolute(filename) .Call( "FileInputStream_new", filename, block_size, close.on.delete, PACKAGE = "RProtoBuf" ) } ) setMethod( "close", "FileInputStream", function(con, ...){ .Call( "FileInputStream_Close", con@pointer, PACKAGE = "RProtoBuf" ) } ) setMethod( "GetErrno", "FileInputStream", function(object){ .Call( "FileInputStream_GetErrno", object@pointer, PACKAGE = "RProtoBuf" ) } ) setMethod( "SetCloseOnDelete", "FileInputStream", function(object, close=FALSE){ invisible( .Call( "FileInputStream_SetCloseOnDelete", object@pointer, isTRUE(close), PACKAGE = "RProtoBuf" ) ) } ) # }}} # {{{ FileOutputStream setGeneric( "FileOutputStream", function(filename, block_size = -1L, close.on.delete = FALSE ){ standardGeneric( "FileOutputStream" ) } ) setMethod( "FileOutputStream", signature( filename = "character", block_size = "integer", close.on.delete = "logical" ), function(filename, block_size = -1L, close.on.delete = FALSE){ if( !file.exists( filename ) ){ if( !file.exists( dirname(filename) ) ){ stop( "directory does not exist" ) } filename <- normalizePath(filename, mustWork=FALSE) } else{ filename <- file_path_as_absolute(filename) } .Call( "FileOutputStream_new", filename, block_size, close.on.delete, PACKAGE = "RProtoBuf" ) } ) setMethod( "flush", "FileOutputStream", function(con){ .Call( "FileOutputStream_Flush", con@pointer, PACKAGE = "RProtoBuf" ) } ) setMethod( "close", "FileOutputStream", function(con, ...){ .Call( "FileOutputStream_Close", con@pointer, PACKAGE = "RProtoBuf" ) } ) setMethod( "GetErrno", "FileOutputStream", function(object){ .Call( "FileOutputStream_GetErrno", object@pointer, PACKAGE = "RProtoBuf" ) } ) setMethod( "SetCloseOnDelete", "FileOutputStream", function(object, close=FALSE){ invisible( .Call( "FileOutputStream_SetCloseOnDelete", object@pointer, isTRUE(close), PACKAGE = "RProtoBuf" ) ) } ) # }}} # {{{ ConnectionInputStream setGeneric( "ConnectionInputStream", function(object, ...){ standardGeneric( "ConnectionInputStream" ) } ) setMethod( "ConnectionInputStream", "connection", function(object, ...){ sc <- summary( object ) if( ! identical( sc[["can read"]], "yes") ){ stop( "cannot read from connection" ) } if( ! identical( sc[["text"]], "binary" ) ){ stop( "not a binary connection" ) } was_open <- isOpen( object ) if( ! was_open ){ open( object ) } .Call( "ConnectionInputStream_new", object, was_open, PACKAGE = "RProtoBuf" ) } ) # }}} # {{{ ConnectionOutputStream setGeneric( "ConnectionOutputStream", function(object, ...){ standardGeneric( "ConnectionOutputStream" ) } ) setMethod( "ConnectionOutputStream", "connection", function(object, ...){ sc <- summary( object ) if( ! identical( sc[["can write"]], "yes") ){ stop( "cannot write to connection" ) } if( ! identical( sc[["text"]], "binary" ) ){ stop( "not a binary connection" ) } was_open <- isOpen( object ) if( ! was_open ){ open( object ) } .Call( "ConnectionOutputStream_new", object, was_open, PACKAGE = "RProtoBuf" ) } ) # }}} RProtoBuf/R/identical.R0000644000176200001440000000146413005133352014414 0ustar liggesusers setGeneric( "identical" ) setMethod( "identical", c(x="Message", y = "Message" ), function( x, y, num.eq = TRUE, single.NA = TRUE, attrib.as.set = TRUE){ .Call( "identical_messages", x@pointer, y@pointer, PACKAGE = "RProtoBuf" ) } ) setMethod( "==", c( e1 = "Message", e2 = "Message" ), function(e1, e2 ){ .Call( "identical_messages", e1@pointer, e2@pointer, PACKAGE = "RProtoBuf" ) } ) setMethod( "!=", c( e1 = "Message", e2 = "Message" ), function(e1, e2 ){ ! .Call( "identical_messages", e1@pointer, e2@pointer, PACKAGE = "RProtoBuf" ) } ) setGeneric( "all.equal" ) setMethod( "all.equal", c( target = "Message", current = "Message" ), function(target, current, tolerance = .Machine$double.eps^0.5, ...){ .Call( "all_equal_messages", target@pointer, current@pointer, tolerance, PACKAGE = "RProtoBuf" ) } ) RProtoBuf/R/initialized.R0000644000176200001440000000035613005133352014764 0ustar liggesusers setGeneric( "isInitialized", function( object, ... ){ standardGeneric( "isInitialized" ) } ) setMethod( "isInitialized", "Message", function(object, ... ){ .Call( "Message__is_initialized", object@pointer, PACKAGE = "RProtoBuf" ) } ) RProtoBuf/R/wrapper_EnumDescriptor.R0000644000176200001440000000221113005133352017152 0ustar liggesusers setGeneric( "value_count", function(object ){ standardGeneric( "value_count" ) } ) setMethod( "value_count", "EnumDescriptor", function(object){ .Call( "EnumDescriptor__value_count", object@pointer, PACKAGE = "RProtoBuf" ) } ) setGeneric( "value", function(object, index, name, number ){ standardGeneric( "value" ) } ) setMethod( "value", "EnumDescriptor", function(object, index, name, number){ has_index <- !missing(index) has_number <- !missing(number) has_name <- !missing(name) if( as.integer(has_index) + as.integer(has_number) + as.integer(has_name) != 1L ){ stop( "need exactly one of `index`, `number` or `name`" ) } if( has_index ){ stopifnot(is.numeric(index)) return( .Call( "EnumDescriptor__getValueByIndex", object@pointer, as.integer(index)-1L, PACKAGE = "RProtoBuf" ) ) } if( has_number ){ stopifnot(is.numeric(number)) return( .Call( "EnumDescriptor__getValueByNumber", object@pointer, as.integer(number), PACKAGE = "RProtoBuf" ) ) } if( has_name ){ stopifnot(is.character(name)) return( .Call( "EnumDescriptor__getValueByName", object@pointer, as.character(name), PACKAGE = "RProtoBuf" ) ) } } ) RProtoBuf/R/lookup.R0000644000176200001440000000077013005133352013770 0ustar liggesusers # attaches the descriptor pool to the search path at the given # position OTABLE <- NULL NAMESPACE <- environment() attachDescriptorPool <- function(pos = 2) { if (is.null(OTABLE)) { ##unlockBinding( "OTABLE", NAMESPACE ) otable <- .Call("newProtocolBufferLookup", pos, PACKAGE = "RProtoBuf") #attach(otable, pos=pos, name="RProtoBuf:DescriptorPool") assign("OTABLE", otable, envir = NAMESPACE, inherits = FALSE) lockBinding("OTABLE", NAMESPACE ) } } RProtoBuf/R/debug_string.R0000644000176200001440000000417213005133352015133 0ustar liggesusers ._toString_Message <- function(x, ...){ .Call( "Message__as_character", x@pointer, PACKAGE = "RProtoBuf" ) } ._toString_Descriptor <- function(x, ...){ .Call( "Descriptor__as_character", x@pointer, PACKAGE = "RProtoBuf" ) } ._toString_EnumDescriptor <- function(x, ...){ .Call( "EnumDescriptor__as_character", x@pointer, PACKAGE = "RProtoBuf" ) } ._toString_FieldDescriptor <- function(x, ...){ .Call( "FieldDescriptor__as_character", x@pointer, PACKAGE = "RProtoBuf" ) } ._toString_ServiceDescriptor <- function(x, ...){ .Call( "ServiceDescriptor__as_character", x@pointer, PACKAGE = "RProtoBuf" ) } ._toString_MethodDescriptor <- function(x, ...){ .Call( "MethodDescriptor__as_character", x@pointer, PACKAGE = "RProtoBuf" ) } ._toString_FileDescriptor <- function(x, ...){ .Call( "FileDescriptor__as_character", x@pointer, PACKAGE = "RProtoBuf" ) } ._toString_EnumValueDescriptor <- function(x, ...){ .Call( "EnumValueDescriptor__as_character", x@pointer, PACKAGE = "RProtoBuf" ) } setMethod( "as.character", "Message", ._toString_Message ) setMethod( "as.character", "Descriptor", ._toString_Descriptor ) setMethod( "as.character", "EnumDescriptor", ._toString_EnumDescriptor ) setMethod( "as.character", "FieldDescriptor", ._toString_FieldDescriptor ) setMethod( "as.character", "ServiceDescriptor", ._toString_ServiceDescriptor ) setMethod( "as.character", "MethodDescriptor", ._toString_MethodDescriptor ) setMethod( "as.character", "FileDescriptor", ._toString_FileDescriptor ) setMethod( "as.character", "EnumValueDescriptor", ._toString_EnumValueDescriptor ) setGeneric( "toString" ) setMethod( "toString", "Message", ._toString_Message ) setMethod( "toString", "Descriptor", ._toString_Descriptor ) setMethod( "toString", "EnumDescriptor", ._toString_EnumDescriptor ) setMethod( "toString", "FieldDescriptor", ._toString_FieldDescriptor ) setMethod( "toString", "ServiceDescriptor", ._toString_ServiceDescriptor ) setMethod( "toString", "MethodDescriptor", ._toString_MethodDescriptor ) setMethod( "toString", "FileDescriptor", ._toString_FileDescriptor ) setMethod( "toString", "EnumValueDescriptor", ._toString_EnumValueDescriptor ) RProtoBuf/R/serialize_pb.R0000644000176200001440000000315113005133352015123 0ustar liggesusers#' Serialize R object to Protocol Buffer Message. #' #' Serializes R objects to a general purpose protobuf message using the same #' \code{rexp.proto} descriptor and mapping between R objects and protobuf #' mesages as RHIPE. #' #' Clients need both the message and the \code{rexp.proto} descriptor to parse #' serialized R objects. The latter is included in the the package installation #' \code{proto} directory: \code{system.file(package="RProtoBuf", "proto/rexp.proto")} #' #' The following storage types are natively supported by the descriptor: #' \code{character}, \code{raw}, \code{double}, \code{complex}, \code{integer}, #' \code{list}, and \code{NULL}. Objects with other storage types, such as #' functions, environments, S4 classes, etc, are serialized using base R #' \code{\link{serialize}} and stored in the proto \code{native} type. #' Missing values, attributes and numeric precision will be preserved. #' #' @param object R object to serialize #' @param connection passed on to \code{\link{serialize}} #' @param ... additional arguments passed on to \code{\link{serialize}} #' @aliases unserialize_pb can_serialize_pb #' @export unserialize_pb #' @export can_serialize_pb #' @export #' @examples msg <- tempfile(); #' serialize_pb(iris, msg); #' obj <- unserialize_pb(msg); #' identical(iris, obj); #' serialize_pb <- function(object, connection, ...){ #convert object to protobuf message msg <- rexp_obj(object); #serialize the message serialize(msg, connection = connection, ...); } unserialize_pb <- function(connection){ #convert object to protobuf message unrexp(read(pb(rexp.REXP), connection)); } RProtoBuf/R/serialize.R0000644000176200001440000000264213005133352014446 0ustar liggesusers # serialization of protobuf messages # at the moment, we grab the payload as a raw vector and send this # to the connection, but in the future, we will directly stream out # the payload to the connection setGeneric( "serialize" ) setMethod( "serialize", c( object = "Message" ) , function( object, connection, ascii = FALSE, refhook = NULL){ stopifnot(object$isInitialized()) iscon <- inherits(connection, "connection") isnull <- is.null( connection ) if( is.character( connection ) ){ # pretend it is a file name if( !file.exists(connection) ){ if( !file.exists( dirname(connection) ) ){ stop( "directory does not exist" ) } file <- normalizePath(connection, mustWork=FALSE) } else{ file <- file_path_as_absolute(connection) } .Call( "Message__serialize_to_file", object@pointer, file, PACKAGE = "RProtoBuf" ) invisible( NULL) } else if( iscon || isnull ) { # first grab the payload as a raw vector, payload <- .Call( "Message__get_payload", object@pointer, PACKAGE = "RProtoBuf" ) if( isnull ){ # just return it if the connection is NULL payload } else{ # otherwise write the payload to the connection # FIXME: we might want to be more clever about this so that # we don't have to store the full payload in memory # but for now it will do just fine writeBin( payload, connection ) invisible( NULL ) } } } ) RProtoBuf/R/with.R0000644000176200001440000000153013144043463013434 0ustar liggesusers# S3 dispatch does not work for some reason generateActiveBindings <- function(data){ env <- new.env( parent = environment() ) xp <- data@pointer names <- .Call( "Message__fieldNames", xp, PACKAGE = "RProtoBuf" ) if( !is.null(names) && length(names) ){ lapply( names, function(x ){ makeActiveBinding( x, function(v){ if( missing(v) ){ # get .Call( "getMessageField", xp, x, PACKAGE="RProtoBuf" ) } else { # set .Call( "setMessageField", xp, x, v, PACKAGE="RProtoBuf") } }, env ) } ) } env } with.Message <- function( data, expr, ...){ envir <- generateActiveBindings(data) eval( substitute( expr ), envir = envir ) } within.Message <- function(data, expr, ... ){ envir <- generateActiveBindings(data) eval( substitute( expr ), envir = envir ) data } RProtoBuf/R/aslist.R0000644000176200001440000000124613005133352013755 0ustar liggesusersas.list.Message <- function( x, ...){ .Call( "Message__as_list", x@pointer, PACKAGE = "RProtoBuf" ) } as.list.Descriptor <- function(x, ...){ # Fields, then nested types, then enum types defined in the message # are returned in a list. .Call( "Descriptor__as_list", x@pointer, PACKAGE = "RProtoBuf" ) } as.list.EnumDescriptor <- function( x, ...){ .Call( "EnumDescriptor__as_list", x@pointer, PACKAGE = "RProtoBuf" ) } as.list.FileDescriptor <- function( x, ...){ .Call( "FileDescriptor__as_list", x@pointer, PACKAGE = "RProtoBuf" ) } as.list.ServiceDescriptor <- function( x, ...){ .Call( "ServiceDescriptor__as_list", x@pointer, PACKAGE = "RProtoBuf" ) } RProtoBuf/R/set.R0000644000176200001440000000274113005133352013252 0ustar liggesusers## TODO(mstokely): Set and fetch are undocumented in Message-class.Rd ## And untested. Are they usful? setGeneric( "set", function(object, field, index, values ){ standardGeneric( "set" ) } ) setMethod( "set", "Message", function(object, field, index, values ){ if( !is.numeric( index ) ){ stop( "index should be numbers" ) } if( inherits( values, "Message" ) ){ values <- list( values ) } # TODO: we need to handle R type = RAWSXP and cpp type == string or bytes if( !identical( length( values ), length(index) ) ){ # TODO: we might want to be more flexible about that later # recycling, ... stop( "`index` should have the same length as `values`" ) } fsize <- size( object, field ) if( any( index > fsize ) || any( index < 1) ){ stop( sprintf( "index should only contain values between 1 and %d", fsize ) ) } .Call( "Message__set_field_values", object@pointer, field, index - 1L , values, PACKAGE = "RProtoBuf" ) # we work by reference invisible( NULL ) } ) setGeneric( "fetch", function(object, field, index ){ standardGeneric( "fetch" ) } ) setMethod( "fetch", "Message", function(object, field, index ){ if( !is.numeric( index ) ){ stop( "index should be numbers" ) } fsize <- size( object, field ) if( any( index > fsize ) || any( index < 1) ){ stop( sprintf( "index should only contain values between 1 and %d", fsize ) ) } .Call( "Message__get_field_values", object@pointer, field, index - 1L , PACKAGE = "RProtoBuf" ) } ) RProtoBuf/R/merge.R0000644000176200001440000000054613144043463013566 0ustar liggesuserssetGeneric( "merge" ) setMethod( "merge", c( x = "Message", y = "Message" ), function( x, y , ... ){ if( !identical( x@type, y@type ) ){ stop(sprintf("incompatible message types, cannot merge '%s' and '%s'", x@type, y@type)) } message <- .Call( "Message__merge", x@pointer, y@pointer, PACKAGE="RProtoBuf") message } ) RProtoBuf/R/read.R0000644000176200001440000000372713005133352013377 0ustar liggesusers setGeneric( "read", function( descriptor, input ){ standardGeneric( "read" ) } ) setMethod( "read", c( descriptor = "Descriptor" , input = "character" ), function(descriptor, input ){ file <- file_path_as_absolute( input ) .Call( "Descriptor__readMessageFromFile", descriptor@pointer, file, PACKAGE = "RProtoBuf" ) } ) setMethod( "read", c( descriptor = "Descriptor", input = "raw" ), function(descriptor, input ){ .Call( "Descriptor__readMessageFromRawVector", descriptor@pointer, input, PACKAGE="RProtoBuf" ) } ) setMethod( "read", c( descriptor = "Descriptor" ), function( descriptor, input ){ if( !inherits( input, "connection" ) ){ stop( "can only read from connections" ) } wasopen <- identical( summary(input)[["opened"]], "opened" ) if( !wasopen ) open( input, "rb") stopifnot(summary(input)[["text"]] == "binary") message <- .Call( "Descriptor__readMessageFromConnection", descriptor@pointer, input, PACKAGE = "RProtoBuf" ) if( !wasopen ) close( input ) message } ) setGeneric( "readASCII", function( descriptor, input, partial=FALSE ){ standardGeneric( "readASCII" ) } ) setMethod( "readASCII", c( descriptor = "Descriptor" , input = "character" ), function(descriptor, input, partial=FALSE){ stopifnot(is.logical(partial), length(partial) == 1) .Call( "Descriptor__readASCIIFromString", descriptor@pointer, input, partial, PACKAGE = "RProtoBuf" ) } ) setMethod( "readASCII", c( descriptor = "Descriptor" ), function( descriptor, input, partial=FALSE){ stopifnot(is.logical(partial), length(partial) == 1) if( !inherits( input, "connection" ) ){ stop( "can only read from connections" ) } wasopen <- identical( summary(input)[["opened"]], "opened" ) if( !wasopen ) open( input, "rb" ) stopifnot(summary(input)[["text"]] == "binary") message <- .Call( "Descriptor__readASCIIFromConnection", descriptor@pointer, input, partial, PACKAGE = "RProtoBuf" ) if( !wasopen ) close( input ) message } ) RProtoBuf/R/add.R0000644000176200001440000000050513005133352013203 0ustar liggesusers setGeneric( "add", function(object, field, values){ standardGeneric( "add" ) } ) setMethod( "add", "Message", function( object, field, values ){ if( is( values, "Message" ) ){ values <- list( values ) } .Call( "Message__add_values", object@pointer, field, values, PACKAGE = "RProtoBuf" ) invisible( object ) } ) RProtoBuf/R/wrapper_FieldDescriptor.R0000644000176200001440000000754413005133352017307 0ustar liggesusers setGeneric( "is_extension", function(object){ standardGeneric("is_extension") } ) setMethod( "is_extension", "FieldDescriptor", function(object){ .Call( "FieldDescriptor__is_extension", object@pointer, PACKAGE = "RProtoBuf" ) }) setMethod( "number", "FieldDescriptor", function(object){ .Call( "FieldDescriptor__number", object@pointer, PACKAGE = "RProtoBuf" ) } ) TYPE_DOUBLE <- 1L TYPE_FLOAT <- 2L TYPE_INT64 <- 3L TYPE_UINT64 <- 4L TYPE_INT32 <- 5L TYPE_FIXED64 <- 6L TYPE_FIXED32 <- 7L TYPE_BOOL <- 8L TYPE_STRING <- 9L TYPE_GROUP <- 10L TYPE_MESSAGE <- 11L TYPE_BYTES <- 12L TYPE_UINT32 <- 13L TYPE_ENUM <- 14L TYPE_SFIXED32 <- 15L TYPE_SFIXED64 <- 16L TYPE_SINT32 <- 17L TYPE_SINT64 <- 18L .TYPES <- sapply(ls( pattern="^TYPE_" ), function(x) get(x)) setGeneric( "type", function(object, as.string = FALSE){ standardGeneric( "type" ) } ) setMethod( "type", "FieldDescriptor", function(object, as.string = FALSE){ type <- .Call( "FieldDescriptor__type", object@pointer, PACKAGE = "RProtoBuf" ) if( as.string ) { names(which(.TYPES == type)) } else { type } } ) CPPTYPE_INT32 <- 1L CPPTYPE_INT64 <- 2L CPPTYPE_UINT32 <- 3L CPPTYPE_UINT64 <- 4L CPPTYPE_DOUBLE <- 5L CPPTYPE_FLOAT <- 6L CPPTYPE_BOOL <- 7L CPPTYPE_ENUM <- 8L CPPTYPE_STRING <- 9L CPPTYPE_MESSAGE <- 10L .CPPTYPES <- sapply(ls( pattern="^CPPTYPE_" ), function(x) get(x)) setGeneric( "cpp_type", function(object, as.string = FALSE ){ standardGeneric( "cpp_type" ) } ) setMethod( "cpp_type", "FieldDescriptor", function(object, as.string = FALSE){ cpptype <- .Call( "FieldDescriptor__cpp_type", object@pointer, PACKAGE = "RProtoBuf" ) if( as.string ) { names(which(.CPPTYPES == cpptype)) } else { cpptype } } ) LABEL_OPTIONAL <- 1L LABEL_REQUIRED <- 2L LABEL_REPEATED <- 3L .LABELS <- sapply(ls( pattern="^LABEL_" ), function(x) get(x)) setGeneric( "label", function(object, as.string = FALSE ){ standardGeneric( "label" ) } ) setMethod( "label", "FieldDescriptor", function(object, as.string = FALSE){ lab <- .Call( "FieldDescriptor__label", object@pointer, PACKAGE = "RProtoBuf" ) if( as.string ) { names(which(.LABELS == lab)) } else { lab } } ) setGeneric( "is_repeated", function(object ){ standardGeneric( "is_repeated" ) } ) setMethod( "is_repeated", "FieldDescriptor", function(object){ .Call( "FieldDescriptor__is_repeated", object@pointer, PACKAGE = "RProtoBuf" ) } ) setGeneric( "is_optional", function(object){ standardGeneric( "is_optional" ) } ) setMethod( "is_optional", "FieldDescriptor", function(object){ .Call( "FieldDescriptor__is_optional", object@pointer, PACKAGE = "RProtoBuf" ) } ) setGeneric( "is_required", function(object ){ standardGeneric( "is_required" ) } ) setMethod( "is_required", "FieldDescriptor", function(object){ .Call( "FieldDescriptor__is_required", object@pointer, PACKAGE = "RProtoBuf" ) } ) setGeneric( "has_default_value", function(object ){ standardGeneric( "has_default_value" ) } ) setMethod( "has_default_value", "FieldDescriptor", function(object){ .Call( "FieldDescriptor__has_default_value", object@pointer, PACKAGE = "RProtoBuf" ) } ) setGeneric( "default_value", function(object ){ standardGeneric( "default_value" ) } ) setMethod( "default_value", "FieldDescriptor", function(object){ .Call( "FieldDescriptor__default_value", object@pointer, PACKAGE = "RProtoBuf" ) } ) setGeneric( "message_type", function(object ){ standardGeneric( "message_type" ) } ) setMethod( "message_type", "FieldDescriptor", function(object){ .Call( "FieldDescriptor__message_type", object@pointer, PACKAGE = "RProtoBuf" ) } ) setMethod( "enum_type", c( object = "FieldDescriptor", index = "missing", name = "missing"), function(object){ .Call( "FieldDescriptor__enum_type", object@pointer, PACKAGE = "RProtoBuf" ) } ) RProtoBuf/R/wrapper_EnumValueDescriptor.R0000644000176200001440000000066213005133352020157 0ustar liggesusers setMethod( "enum_type", c( object = "EnumValueDescriptor", index = "missing", name = "missing"), function(object, index, name){ .Call( "EnumValueDescriptor__enum_type", object@pointer, PACKAGE = "RProtoBuf" ) } ) setGeneric( "number", function(object){ standardGeneric( "number" ) } ) setMethod( "number", "EnumValueDescriptor", function(object){ .Call( "EnumValueDescriptor__number", object@pointer, PACKAGE = "RProtoBuf" ) } ) RProtoBuf/R/field_count.R0000644000176200001440000000515013005133352014747 0ustar liggesuserssetGeneric( "field_count", function(object){ standardGeneric( "field_count" ) } ) setMethod( "field_count", "Descriptor", function(object){ .Call( "Descriptor__field_count", object@pointer, PACKAGE = "RProtoBuf" ) } ) setGeneric( "nested_type_count", function(object){ standardGeneric( "nested_type_count" ) } ) setMethod( "nested_type_count", "Descriptor", function(object){ .Call( "Descriptor__nested_type_count", object@pointer, PACKAGE = "RProtoBuf" ) } ) setGeneric( "enum_type_count", function(object){ standardGeneric( "enum_type_count" ) } ) setMethod( "enum_type_count", "Descriptor", function(object){ .Call( "Descriptor__enum_type_count", object@pointer, PACKAGE = "RProtoBuf" ) } ) setGeneric( "field", function(object, index, number, name){ standardGeneric( "field" ) } ) setMethod( "field", "Descriptor", function( object, index, number, name){ has_index <- !missing(index) has_number <- !missing(number) has_name <- !missing(name) if( as.integer(has_index) + as.integer(has_number) + as.integer(has_name) != 1L ){ stop( "need exactly one of `index`, `number` or `name`" ) } if( has_index ){ return( .Call( "Descriptor__field", object@pointer, as.integer(index)-1L, PACKAGE = "RProtoBuf" ) ) } if( has_number ){ return( .Call( "Descriptor__FindFieldByNumber", object@pointer, as.integer(number), PACKAGE = "RProtoBuf" ) ) } if( has_name ){ return( .Call( "Descriptor__FindFieldByName", object@pointer, as.character(name), PACKAGE = "RProtoBuf" ) ) } } ) setGeneric( "nested_type", function(object, index, name){ standardGeneric( "nested_type" ) } ) setMethod( "nested_type", "Descriptor", function(object, index, name ){ has_index <- !missing(index) has_name <- !missing(name) if( !identical( as.integer(has_index) + as.integer(has_name), 1L ) ){ stop( "need exactly one of `index` or `name`" ) } if( has_index ){ return( .Call( "Descriptor__nested_type", object@pointer, as.integer(index)-1L, PACKAGE = "RProtoBuf" ) ) } if( has_name ){ return( .Call( "Descriptor__FindNestedTypeByName", object@pointer, as.character(name), PACKAGE = "RProtoBuf" ) ) } } ) setMethod( "enum_type", "Descriptor", function(object, index, name){ has_index <- !missing(index) has_name <- !missing(name) if( !identical( as.integer(has_index) + as.integer(has_name), 1L ) ){ stop( "need exactly one of `index` or `name`" ) } if( has_index ){ return( .Call( "Descriptor__enum_type", object@pointer, as.integer(index)-1L, PACKAGE = "RProtoBuf" ) ) } if( has_name ){ return( .Call( "Descriptor__FindEnumTypeByName", object@pointer, as.character(name), PACKAGE = "RProtoBuf" ) ) } }) RProtoBuf/R/rpc.R0000644000176200001440000000454713005133352013251 0ustar liggesusers setGeneric( "invoke", function( method, message, protocol){ standardGeneric( "invoke" ) } ) check_valid_implementation <- function( method, implementation ){ if( !is.function( implementation ) ){ stop( "should be a function" ) } if( !identical( length(formals(implementation)), 1L ) ){ stop( "should have exactly one argument" ) } invisible(NULL) } check_valid_input_message <- function( method, message){ # check that message is of correct type valid <- .Call( "valid_input_message", method@pointer, message@pointer, PACKAGE = "RProtoBuf" ) if( !valid ){ expected <- .Call( "get_method_input_type", method@pointer, PACKAGE = "RProtoBuf" )@type stop( sprintf( "invalid input message, expecting a message of type : %s", expected ) ) } } setMethod( "invoke", c(method = "MethodDescriptor", message = "Message", protocol = "missing" ), function( method, message, protocol){ # check that the message is valid check_valid_input_message( method, message ) # grab the implementation if( exists( method@name, envir = IMPLEMENTATIONS ) ){ impl <- get( method@name, envir = IMPLEMENTATIONS ) check_valid_implementation( method, impl ) result <- impl( message ) valid <- .Call( "valid_output_message", method@pointer, result@pointer, PACKAGE = "RProtoBuf" ) if( !valid ){ stop( "invalid method output" ) } result } else{ warning( "unimplemented method, returning output message prototype" ) .Call( "get_method_output_prototype", method@pointer, PACKAGE = "RProtoBuf" ) } # return the message } ) setMethod( "invoke" , c( method = "MethodDescriptor", message = "Message", protocol = "RpcHTTP"), function(method, message, protocol ){ # check that the message is valid check_valid_input_message( method, message ) root <- protocol@root[1] if( ! grepl( "^/", root ) ) root <- paste( "/", root, sep = "" ) if( ! grepl( "/$", root ) ) root <- paste( root, "/", sep = "" ) url <- sprintf( "http://%s:%d%s?service=%s&method=%s", protocol@host, protocol@port, root, method@service, method$name() ) reader <- basicTextGatherer() header <- c( "Content-Type" = "application/x-protobuf", "Accept" = "application/x-protobuf" ) curlPerform( url = url, httpheader = header, postfields = serialize(message, NULL) , writefunction = reader$update ) response <- charToRaw( reader$value() ) read( method$output_type(), response ) } ) RProtoBuf/R/zzz.R0000644000176200001440000000113413005133352013307 0ustar liggesusers .onLoad <- function(libname, pkgname ){ ##minversion <- packageDescription(pkgname, lib.loc=libname)$MinimumLibProtoVersion ##minversion <- as.integer( gsub( "[[:space:]]+", "", minversion ) ) ##.Call( "check_libprotobuf_version", minversion, PACKAGE = "RProtoBuf" ) readProtoFiles( package=pkgname, lib.loc=libname ) attachDescriptorPool( pos = length(search()) ) options("RProtoBuf.int64AsString" = FALSE) #if( exists( ".httpd.handlers.env", asNamespace( "tools" ) ) ){ # e <- tools:::.httpd.handlers.env # e[["RProtoBuf"]] <- RProtoBuf.http.handler #} } RProtoBuf/R/wrapper_MethodDescriptor.R0000644000176200001440000000071613005133352017476 0ustar liggesusers setGeneric( "input_type", function(object){ standardGeneric( "input_type" ) } ) setGeneric( "output_type", function(object){ standardGeneric( "output_type" ) } ) setMethod( "input_type", "MethodDescriptor", function(object){ .Call("MethodDescriptor__input_type", object@pointer, PACKAGE = "RProtoBuf" ) } ) setMethod( "output_type", "MethodDescriptor", function(object){ .Call("MethodDescriptor__output_type", object@pointer, PACKAGE = "RProtoBuf" ) } ) RProtoBuf/R/containing_type.R0000644000176200001440000000174613005133352015655 0ustar liggesusers setGeneric( "containing_type", function(object){ standardGeneric( "containing_type" ) } ) setMethod( "containing_type", "Descriptor", function(object){ retval <- .Call( "Descriptor__containing_type", object@pointer, PACKAGE = "RProtoBuf" ) if (length(retval@type) == 0) { # Descriptors do not always have containing types. # In such cases NULL is better return value than malformed Descriptor. return(NULL) } else { return(retval) } } ) setMethod( "containing_type", "EnumDescriptor", function(object){ retval <- .Call( "EnumDescriptor__containing_type", object@pointer, PACKAGE = "RProtoBuf" ) if (length(name(retval)) == 0) { # If this enum type is nested in a message type, this # is that message type. Otherwise, NULL. return(NULL) } else { return(retval) } } ) setMethod( "containing_type", "FieldDescriptor", function(object){ # Never NULL .Call( "FieldDescriptor__containing_type", object@pointer, PACKAGE = "RProtoBuf" ) } ) RProtoBuf/R/wrapper_CodedInputStream.R0000644000176200001440000000443513005133352017433 0ustar liggesusers setGeneric( "ReadRaw", function(object, size ){ standardGeneric( "ReadRaw" ) } ) setMethod( "ReadRaw", c( object="ZeroCopyInputStream", size = "integer" ), function(object, size){ .Call( "ZeroCopyInputStream_ReadRaw", object@pointer, size, PACKAGE = "RProtoBuf" ) } ) setMethod("ReadRaw", c( object="ZeroCopyInputStream", size = "numeric" ), function(object, size) { if (size %% 1 == 0) { .Call( "ZeroCopyInputStream_ReadRaw", object@pointer, as.integer(size), PACKAGE = "RProtoBuf" ) } else { stop("Size must be a whole number.") } } ) setGeneric( "ReadString", function(object, size ){ standardGeneric( "ReadString" ) } ) setMethod( "ReadString", c( object="ZeroCopyInputStream", size = "integer" ), function(object, size){ .Call( "ZeroCopyInputStream_ReadString", object@pointer, size, PACKAGE = "RProtoBuf" ) } ) setMethod("ReadString", c( object="ZeroCopyInputStream", size = "numeric" ), function(object, size) { if (size %% 1 == 0) { .Call("ZeroCopyInputStream_ReadString", object@pointer, as.integer(size), PACKAGE = "RProtoBuf" ) } else { stop("Size must be a whole number.") } } ) setGeneric( "ReadVarint32", function(object){ standardGeneric( "ReadVarint32" ) } ) setMethod( "ReadVarint32", c( object="ZeroCopyInputStream"), function(object){ .Call( "ZeroCopyInputStream_ReadVarint32", object@pointer, PACKAGE = "RProtoBuf" ) } ) setGeneric( "ReadLittleEndian32", function(object){ standardGeneric( "ReadLittleEndian32" ) } ) setMethod( "ReadLittleEndian32", c( object="ZeroCopyInputStream"), function(object){ .Call( "ZeroCopyInputStream_ReadLittleEndian32", object@pointer, PACKAGE = "RProtoBuf" ) } ) setGeneric( "ReadLittleEndian64", function(object){ standardGeneric( "ReadLittleEndian64" ) } ) setMethod( "ReadLittleEndian64", c( object="ZeroCopyInputStream"), function(object){ .Call( "ZeroCopyInputStream_ReadLittleEndian64", object@pointer, PACKAGE = "RProtoBuf" ) } ) setGeneric( "ReadVarint64", function(object){ standardGeneric( "ReadVarint64" ) } ) setMethod( "ReadVarint64", c( object="ZeroCopyInputStream"), function(object){ .Call( "ZeroCopyInputStream_ReadVarint64", object@pointer, PACKAGE = "RProtoBuf" ) } ) RProtoBuf/R/wrapper_ServiceDescriptor.R0000644000176200001440000000154113005133352017653 0ustar liggesuserssetGeneric( "method_count", function(object ){ standardGeneric( "method_count" ) } ) setMethod( "method_count", "ServiceDescriptor", function(object){ .Call( "ServiceDescriptor_method_count", object@pointer, PACKAGE = "RProtoBuf" ) } ) setGeneric( "method", function(object, index, name ){ standardGeneric( "method" ) } ) setMethod( "method", "ServiceDescriptor", function(object, index, name){ has_index <- !missing(index) has_name <- !missing(name) if( as.integer(has_index) + as.integer(has_name) != 1L ){ stop( "need exactly one of `index` or `name`" ) } if( has_index ){ return( .Call( "ServiceDescriptor_getMethodByIndex", object@pointer, as.integer(index)-1L, PACKAGE = "RProtoBuf" ) ) } if( has_name ){ return( .Call( "ServiceDescriptor_getMethodByName", object@pointer, as.character(name), PACKAGE = "RProtoBuf" ) ) } } ) RProtoBuf/vignettes/0000755000176200001440000000000013164671424014154 5ustar liggesusersRProtoBuf/vignettes/figures/0000755000176200001440000000000013005133352015603 5ustar liggesusersRProtoBuf/vignettes/figures/histogram-mapreduce-diag1.pdf0000644000176200001440000006024713005133352023232 0ustar liggesusers%PDF-1.3 % 4 0 obj << /Length 5 0 R /Filter /FlateDecode >> stream x՛I +8)">TQOI\^@xo:0TΣ2$;I,I^[w2U Xa~le1a1<Ő'[Լ3B=b^\ˢd^y (SԼ.,j^3{l춳} NN)%6Њ V}e)VSSAa_8S"$dETH1㈏^H ZlH=%-TE,IF٦bEI6e ٳ(?30>WaVԊ8O͈bEXQ~^KV%F+ jEZQV9 (YQ?y#Ŋa,V]‹]YB\i} RqlEnAiWbј$+1a ɊDf@يbE7=b)GdŊ"`\ۤo͌HB]*Q$F1*Fل`顄,>&\b-&e@Dt<Cl2ۮA7zapMtI׸5kkgn^onI楹߿3OO71skrIe7!(=e,vSw*]I]:qu7-b̖,:'ahf|}B2&Ү$By]!#C^o[/ r` r uO  9ls1 K\ Αh. (pc[ N~$BR"SLg$*PAx'(B@9gn%gkr0aGp4f̧qgޗś/?/-| :1up >?#,Ͻ˜prÿnwBX| ,֋7"t7: VO{\=Ǎ?3?<ϹXRLxuWw'R}UTFFIJݶ^={sj;HX[41WEω*:3W'@' ~JޱvpݗloHTēPIs:0/0b[@D2sVݜ^s4 $b*x۴[mQۆ IR53uZ!%6xLztʁW|6s3 krBa~%XE"cDV%[{"zLY0_Vzޏ'ɴ0DcD`sӊa{.P-Sx%WhzA^%6.]b/ #Dݕ._0_wkCe+8.NrŽK +f IҊD;!)Le]qZv#wNgκsK .Q7>5\8\NS.,\4D-**;1 2UF:'e9ՅXnLc,%vBVݬNсH1%35 'x|Q*TFH`@h IrNſT@)▵lr}GǚJJo#g*IOJ9')OiE݉7J @!rXel7D7x9h`^36L(C,In0d؊=tLn54Y9_jNB_1"7+̵i]u1W䳧mZ ^񝴆nQf~%# JqJ!b\+{<-J;5ܰ(1e-t$cmֱ6Ig. O8 '5L:YqT"a=V}WuMʑIÁ=Mp͵31kwC> endobj 6 0 obj << /ProcSet [ /PDF /Text ] /ColorSpace << /Cs1 7 0 R /Cs2 8 0 R >> /Font << /TT2.0 10 0 R /TT1.0 9 0 R >> >> endobj 11 0 obj << /Length 12 0 R /N 3 /Alternate /DeviceRGB /Filter /FlateDecode >> stream xUoT>oR? XGůUS[IJ*$:7鶪O{7@Hkk?<kktq݋m6nƶد-mR;`zv x#=\% oYRڱ#&?>ҹЪn_;j;$}*}+(}'}/LtY"$].9⦅%{_a݊]hk5'SN{<_ t jM{-4%TńtY۟R6#v\喊x:'HO3^&0::m,L%3:qVE t]~Iv6Wٯ) |ʸ2]G4(6w‹$"AEv m[D;Vh[}چN|3HS:KtxU'D;77;_"e?Yqx endstream endobj 12 0 obj 1047 endobj 7 0 obj [ /ICCBased 11 0 R ] endobj 13 0 obj << /Length 14 0 R /N 1 /Alternate /DeviceGray /Filter /FlateDecode >> stream xUMlUgŠU+'ZEi *:i"Rm֛ew6QOT! zZ~^TTH 8YCz̛fK}D|XU$~uB}NRI/<Ƈ7ޅצר܎{%U:,vsks$Gȭ!|];DbUxfϵt$Y:卵HNIVz-#Cz [Eydʈx0q+G#؅бGU ZT扞ȗsgWs;<ć̫|xHK}/wѴ%Q)o))_)ϕ$+ʊrY||ݧ(u[=vfq1ܱAk3o,mEp gK~nߥvjjyaqmBim ր6vq5y=klfUg=.SfE#fsH޵]:QV݇I!H&ɒf3Ì}sDf7N=ΈY1:yɄsd{}^_{4md(EsߚbPןY"s>aض@ Y'~Gjju72J&"j endstream endobj 14 0 obj 1088 endobj 8 0 obj [ /ICCBased 13 0 R ] endobj 3 0 obj << /Type /Pages /MediaBox [0 0 612 792] /Count 1 /Kids [ 2 0 R ] >> endobj 15 0 obj << /Type /Catalog /Pages 3 0 R >> endobj 9 0 obj << /Type /Font /Subtype /TrueType /BaseFont /EJTTYZ+Helvetica /FontDescriptor 16 0 R /Encoding /MacRomanEncoding /FirstChar 32 /LastChar 117 /Widths [ 278 0 0 0 0 0 0 0 333 333 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 722 0 0 0 0 278 0 0 0 0 0 778 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 556 556 0 556 556 278 556 556 222 0 0 0 833 556 556 556 0 333 500 278 556 ] >> endobj 16 0 obj << /Type /FontDescriptor /FontName /EJTTYZ+Helvetica /Flags 32 /FontBBox [-951 -481 1445 1122] /ItalicAngle 0 /Ascent 770 /Descent -230 /CapHeight 737 /StemV 0 /XHeight 637 /MaxWidth 1500 /FontFile2 17 0 R >> endobj 17 0 obj << /Length 18 0 R /Length1 10384 /Filter /FlateDecode >> stream xZ xTյ^yLf&EBB9$G $ LP#p*Q ׷< ! RZ]j-g{/jds&Đw?3k>k{sWu-  jJ:/&lriײUɼҽlM mIc\܉<qz$cp5j]{ն#>$]w=q} {Za+(v-U۴埂^}_/v\ōR̅a5AՖ9 1h̊4 "6%{QghXNH@bFR1w<IdbF~_NP<*p#/a!s @00T8).FM=BGIi 0L(y$FKO0I_ZSVF/qGwhlp7G D|Fk2+kFڣ=]+Vw[Hчz:mvȊ.;#見Wyύ^*UMGU=bOh{ꖛ޵i]+λ*VKj]zW]b.i+FV/f4FY5W,ZYб! HHq J.I=!(>Lg" 0oTe 3$x ؾv8j|fv3 $Ƽvؐxҡ{ X8'SGc`k^ILdC%c8C;NAr$< O~2L$.'>DQ ^Gȇa{''Dd[[a<,jr;&vJ5>8a*޵p<?7 eut7DQA3pH:ތc:E8Gz#A)(=e\T#Nzש^Iga/o__2,cdTf<̬bv὇3/$v;e7ӋW7f3ř8;PfŐtIi8ϒ6CZBD #BRy( g]6 [x%e%v {Jpy(E÷ gtϋ&tmVd4u)jR!jM7l2AmmaAۨVTeo6Q\VRĖKǴ-őD-lo*7Fi#UfotPNGt }>|[mFI:ZWZMN2'[2"0mX":UQXGۖD4UW9}f,â&|GN( <UJ-lmQUKֻ?}~xTe ԴuDև\)*܌F/vKmlnLH<@N%vkBu7W;V"B}S]˙e>9g[dgضhH!Qb%~dD :Joq W3a.G~D):eڢ7J2׺_awȋPe3oM:S\[m >RYi ;mNi~{9żV=4Q.M Л̞E}B67Hbc 'Go[ْ-c&' 2}d{k5x}Ӗyk(LL@9llB`.Qlv$;'`?R?6kV \;q1MsUΨXՌ{)z%[p[nyd/b}}RM~_l_Oҷd>F`l8\y}Ny|~,a:ED.|C~'|-F8 rLBxI7!\GF&'#p7𔯃pBzӛA% i#|#323!³³G8 zy 7!;72y r;WFx7pByӛ^<7K:h;;7n=%T)nf*{K\)3wARR R-0\  ʐzM1bq.1{aM\ዽGIwwGj< 7♖sF0N"ƽr /5Kح[~HME%s4U$Ϯ\t0] 24n $4.'e^X >}SbLݗx(n/בI¤W-VCq<3'ELlܷ 6feͺV7x1ꎪAEE~xNZ C"b#s)ضvkMĢj);ž_?_Y}go#*NJXT z0f(p#K n2L$N^|oFb. S5uD@Pj)H BH hvMI&f>)k  dz<<ųR'b@aPބ,u_K`|t(OOVSaB]=̡}//R$w >`PT'/w7_t_NVY~3 ARHkHbC K.IRVx~ZpB*pIMspQ.ʐO;Rm*;-ߊ C`(Eqa(GJ6h P !`Jaʪ6#],=t$t u >0zG3Om{>=~ܡJωY~OIo$59S`ϡ%M.1zE T ze[2EHv+WrPH}>`$%f$FEj0L0ӓ qfRs֋읻n='SϱX7'>Gu]=c.a]t <&2)rsF)ȵRI|<Ӟl#UO`2Uh5ꔀ;-HBpj\phҌ&HҜB\9_Z0TS,Ml)ӥ٠%;P.*,StO)}Y ;׽'I v&s0S^wvX*:fωHٳË7P9M(!f)cEJ m.(|#bWQ"'9*z b2|=cTFx VUBhjTTj@pJ|n;sQLG!wGEN=#)6xmh3kyEEy k0@Oi BN~7PsTuxpx=ǻwm+XW{9d׽G6O(܎ۊR '3P a T:J+!ACRpπ`jTR#92tyi)i{dYkM/:*'wS:zh7c \WrID~b'iyg&j|Sӧ-M_\^VNt6Ҹ̳9L겙sL j @Z2~ryٕC/Yl!뤌 pk 4ٸo`316`d64MRH0PƇ`w݂qhmnq%WrKݗ>O(xɘPp!ڷd]4')68鉥˫3f}\OyZ^]ZvhΉSg5v;7_~o(K']֡)Y 1XJ4Qh_05f-)w跬~KduCWUDV$&X$.<4秤> endobj 19 0 obj << /Type /FontDescriptor /FontName /HNSKIB+Helvetica /Flags 32 /FontBBox [-951 -481 1445 1122] /ItalicAngle 0 /Ascent 770 /Descent -230 /CapHeight 717 /StemV 0 /XHeight 637 /MaxWidth 1500 /FontFile2 20 0 R >> endobj 20 0 obj << /Length 21 0 R /Length1 12920 /Filter /FlateDecode >> stream x{ xT9箳d2L&3ɾ@ƐHD!AIH l5`"RԺ5(2(hk+ZEj+*]q03{>ӧsMײ( M9I".iu>s)1u_/^9| uG{K[]bu<%]A.gpz>-Kc~yr=v  o\><Cyahu-H! !܎X[P%_"(󒯿iSl i#~Gz qP}ZUfF==,J O#}P;` Y䀂uܡ8rqoIl[69~!1U Gеu0R\8yX xQ":>p|"xqb!y"g>2X~?8g_ؚ»[! lepQG[?uGpAQPr/;|!C=>ՑkG2Ü0'q[+^p{P*38EXjHUJ'W Rv|T_AyƫZ.6!WHRբJTrQ@?R ˁ#"/r!4'A1D}(10/F>0%(ĚR2$"E& ~<ģGݥRMQe?Ji?=cJ}Cp1K Q{w-)u+tw.WhvW40{Z ;i3x[vм=n/.t;wKGѼ; t+-GZ˖5 #ZVwUF'[F*7YM>>>5*=.bA}ٽ]ΊS`Y AgKcyAcrĝFjJzB\ygy,7S zqB}*h(Rh+z?ix[v A h\U(pE fFt1h uõMx"Wmx;-I%wG>cjJ+"_FOFGA&dGweh o1sٰ2<d>/ |pDI $t9C~,`3O2gd'p{F6D~-~Dh\F-N4 \`΢s5! Pa-\\W- 3\/K|E`#hH=i%KHy0 L*3U"sr5j]g7"nWz Ff.&w_o/X*#ly xX  Ն:QJYL" /[wh3=}ُNY Sls;awBEWOy=$D-j1NQ)r(+ܕΠ9zUUn(; :}-u7jd 6202%$#Yv]v P~ IT78+ nvV+;z+3CNG)A4e5X4ZAx*ZڂӦ7T'\Mu A=ls= fZjdZΥI AӪOUo*6$ʖ`1 .6ZFMw´Ɔ ~d B Π]] Eu րUA4aH5.X2ny˼&p4791SF)Հg9Wz-I{![t_#e.|& r`O 4:c5/,Y*kͽqS0^v~ ں=[[Z[xKD;FJ(wSeUwt=\qS)i(A=(i LBi 1GB~lT9НNYmA9<*АRf\IynuV:;XCG{ocP'F퍍`,:{a3@.5eaPv:(S;azC.^ W“}“G$% OQP{QLo4vJ> BN;F$l(<_D߇ ߋ#BYs#]#$rgEr<&iQ)y?P{Ynzߏv?6fC{@78ŐTxh-@]Kn癠eи?RW2ԝhuonAT/`x,4E!9 Z;?%ăT("]tHc >Yj Q"a1<+V$%f s}SqOpWp#bKYyUQb@I2X_b):Z2A܁Ќ0 yvNƥB;[s b)@M9{V6! kd:dO*4Um1v-3Gj Y?=T[^*-D5jQ>ϛ[#sΚ4=w-B$N'~$_Etym3o)o rPA@)jSu%.@I&Z]CЅbЇ7ӎ-Ш}^&/A-̤eVR,v)> 6]mս.we{# ][%oj@C#oC%~n9V}$|lS؂1^;?ϠxL\l~SygF.r ev!H3 p*# YXE@&o L>6>曗 HB? 'n C8/dYA ;8$$Sw5}'\[s9ٺ xlƭ9Mzu}J  )8'x*AXgv1!p?}LK8.Ee# "'c&xIaee$"y'DMfUOae[w16FHP wۊ)\yNBBya$2t''Pj^@@(pC -GuȢx{r̗%y2a*< (!:&sU]}vˁM˖eMKuc Fƽq~[OsYܩk^ҷV\f|8@q t! qոk M'OBȂ-Pv9ڥzF +ѨgdO"DD VEy#[^*mkJ%EX-*&@4\8c>ۥa\4 ؁&' N73i ϋXϓ%o,i16\*UsE9y.gNxm{YϹ;zdƗO${&wدOQU"9x-P&y[T+eD!$F$gXQ}VVmaǥɲ\%j)T-zRy,9ϺniW(I%RڠsddO\I8Hě=V/PFqbi(`N3`Ӑ̧H΄$QkN#$n%-MNK(ii> jt˥bH?&9/5)Փxd gNw,Ɖ˜v2󿘾k}'ϹRp >}c?GkKk8'<{_^'#=W"msYI^}kcł&h}. xj䒀B5#GQ/(f[Lg]I C"-Q"hIp𖖥Өr2^ ߆eTܩ].|1WX3E HxX9bU"Q1 B̮VڋHX1)Mh'|I&[rgT{D()juB69Wh?gx'F>{cu01] Ε8)c I[< ޅ̉ .dtA-&ąv \Pf4%KU8o1Nx=ѣ x $7LXV-q#wIkN=`P>bSMe&5۔jOƬeNjts쩪iKbG|;P뷿×)tG?b=Qg Ok{$LH4DBV5SHcq8׹N5O/KHYkF^Z9$:YqAT'QRh5z"QNA>TbҪ;rȼ͛wL5#CH]a}t͝sK27ׂwff٣g=o qv`BBIbG4VgUpĵlwgfʕcE( r/R԰JMZ@C c2 ck!y/f1KBeD Tl4! 3eJ+(;|5?[:Jɷڷmlmݹ/y6x B8%fUhE wjjj//zoW#ntrb7)L]گZ ՒXZVv×/[&# X d!^$O@iwaUZD@xPmW[[\ߪpo}ϗ#o}~ $c$N!o'lۀ3 2*z[`e`NI^éH<7}@Ћ~+8ʜǯ0ߗ]tbVלג"Jm'`tmnTxcpX1c,rQ>K|/`Hv*jTŎC%rp0FUz5+=I ^^h/RT^r[]A"ԐHG5󤦥>ZDY.+X@@m 0xZ/'v>~Gp{N^ ;)>a7;iѝO~sM7gNf1eʇb6$&-ji/2ZvUo xCETkRcF}U&n/ f ={wtPlYu΁۹1 y;_tyjS?Šb ec}X-ke|}i1&UgIRXoȵvy|٘Lcff+U ^͒}:TD9 |Ka RPؾS MGu'z( Frx2cOb_Rv67fYL zr4zw%y}y-"RLWy_T|~#e v~)r 'prggnOɖMpO\w=K{~\+2úi_A3#ϝ{OOdHJeԈ&$Xn\uqDΛ "2C1_t{V"'㲛qS`4~XL/%nfCWo,5-ԀQa2ݰ$#6Ӹ6=jSO.Y1sA6kK+g?uǦXreѴM})ϼA9O;f x Ow ^If5XR7+VjEJjÙfYxTJL;",&MK+<-={M?0#ah.))ϺNRJѺ'y'?f>>cH|U|TGr͂ҮUX@|`& amsFd$C(ӫ@si &(qqP^ՐF0$qD40#K&cq D?=ďwx>ju};l>p2s)0Ñpu0&z`*Ľ&":mo7nS$lM'[ҕL]g`ڌ zY/JqFHEEIZ,jR6gy1 @&T8Y4y pG#Ǻv.\۷zf>ٶ}M)%?qw~buC-p5x2XV%J)}"eC\0E 8X1uL-^ l,hygF1qf:A~ {2C- ,.s7 g~X(>eؕʧ${|JפI3}{W*WƭTu<]޾tfՐ` ̔xx')NΦ̯:gNSd 2(˕eufiBWXsTzeZsF7!1]]nQRi #LkKp!|·!B\*ZhKЛ]B$U蓻#CDpBh!1IK,r0sx #HQ8^BnY4"vřyfeϜyWE2XI٦Ys'*S-:{VzŶ^xY7%S "fti\ ⨥k,21J/Ƞ230׍laimEtdH,iZjIa؛Oͻx 9qzDߚY7s"l Wl'綂!'#8mÜU=DEgѧ+wA"N%G|efp2~j~[7*(RXj7G@c%b.f?r~3.?i3Sxny^`& dst0uzn/'"|F*ܣ<*'Vܛ"f{H8~,B©y2Idgrn!rS+i|XjkH:tE5B,K2}eCZa_298ݼEEᢢQ3s: . ce8 p"N;Y|:ͺ&P CZ黤_~kXokfU6h +F.x˰Ӹԏ*40-^:\KNlBRoUT0o|HC#贷c :bQ.ʵd!*°l%ZaL7c\ Y!OO(0އ[˞yOJUf HeG6GRd /ǻd= /08A3A"g|Tt T)}#Y /!kҷuhP# 3`xLJyx㇪jTU/nZ0E!uC|{So`* PPpz]!W ,X0T4t>:硑2FQu~zzzΨQQQQ;G)UoƿuT}zۨ7ި@[`T}ѨQu4nz.nQQeKqGwh+W endstream endobj 21 0 obj 8609 endobj 22 0 obj (histogram-mapreduce-diag1) endobj 23 0 obj (Mac OS X 10.7.5 Quartz PDFContext) endobj 24 0 obj (Murray Stokely) endobj 25 0 obj (OmniGraffle Professional 5.4.3) endobj 26 0 obj (D:20130630033847Z00'00') endobj 1 0 obj << /Title 22 0 R /Author 24 0 R /Producer 23 0 R /Creator 25 0 R /CreationDate 26 0 R /ModDate 26 0 R >> endobj xref 0 27 0000000000 65535 f 0000023925 00000 n 0000004062 00000 n 0000006746 00000 n 0000000022 00000 n 0000004042 00000 n 0000004166 00000 n 0000005461 00000 n 0000006710 00000 n 0000006879 00000 n 0000014343 00000 n 0000004290 00000 n 0000005440 00000 n 0000005497 00000 n 0000006689 00000 n 0000006829 00000 n 0000007266 00000 n 0000007491 00000 n 0000014322 00000 n 0000014759 00000 n 0000014984 00000 n 0000023684 00000 n 0000023705 00000 n 0000023749 00000 n 0000023801 00000 n 0000023834 00000 n 0000023883 00000 n trailer << /Size 27 /Root 15 0 R /Info 1 0 R /ID [ ] >> startxref 24045 %%EOF RProtoBuf/vignettes/figures/HistogramTools.pdf0000644000176200001440000001053713005133352021262 0ustar liggesusers%PDF-1.4 %ρ\r 1 0 obj << /CreationDate (D:20160710180052) /ModDate (D:20160710180052) /Title (R Graphics Output) /Producer (R 3.3.1) /Creator (R) >> endobj 2 0 obj << /Type /Catalog /Pages 3 0 R >> endobj 7 0 obj << /Type /Page /Parent 3 0 R /Contents 8 0 R /Resources 4 0 R >> endobj 8 0 obj << /Length 509 /Filter /FlateDecode >> stream xn0EYڋ2r6F@EIHilmHL` څd_yAXٕ+v;&nݲK韯~JA8''V>=Ow)ɪ^[xh@`U_DRPd_gܙ.r[?M&2_ie9~p0|f7"*N vY> .E\feR.KQfqywMU3sȅ\</o`D˕^<+%qSz^%SUZeӽJ'qAl7 E`.LkuQf.}xE(3WhQ܏X?c;ݝrkQ/Rop35;8ffO=}tF U*蠍HewIT)ViΰO?C?vmmkU>]2-s=swgq"s( `rendstream endobj 3 0 obj << /Type /Pages /Kids [ 7 0 R ] /Count 1 /MediaBox [0 0 504 504] >> endobj 4 0 obj << /ProcSet [/PDF /Text] /Font <> /ExtGState << >> /ColorSpace << /sRGB 5 0 R >> >> endobj 5 0 obj [/ICCBased 6 0 R] endobj 6 0 obj << /Alternate /DeviceRGB /N 3 /Length 2596 /Filter /FlateDecode >> stream xwTSϽ7PkhRH H.*1 J"6DTpDQ2(C"QDqpId߼y͛~kg}ֺLX Xňg` lpBF|،l *?Y"1P\8=W%Oɘ4M0J"Y2Vs,[|e92<se'9`2&ctI@o|N6(.sSdl-c(2-yH_/XZ.$&\SM07#1ؙYrfYym";8980m-m(]v^DW~ emi]P`/u}q|^R,g+\Kk)/C_|Rax8t1C^7nfzDp 柇u$/ED˦L L[B@ٹЖX!@~(* {d+} G͋љς}WL$cGD2QZ4 E@@A(q`1D `'u46ptc48.`R0) @Rt CXCP%CBH@Rf[(t CQhz#0 Zl`O828.p|O×X ?:0FBx$ !i@ڐH[EE1PL ⢖V6QP>U(j MFkt,:.FW8c1L&ӎ9ƌaX: rbl1 {{{;}#tp8_\8"Ey.,X%%Gщ1-9ҀKl.oo/O$&'=JvMޞxǥ{=Vs\x ‰N柜>ucKz=s/ol|ϝ?y ^d]ps~:;/;]7|WpQoH!ɻVsnYs}ҽ~4] =>=:`;cܱ'?e~!ańD#G&}'/?^xI֓?+\wx20;5\ӯ_etWf^Qs-mw3+?~O~endstream endobj 9 0 obj << /Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences [ 45/minus 96/quoteleft 144/dotlessi /grave /acute /circumflex /tilde /macron /breve /dotaccent /dieresis /.notdef /ring /cedilla /.notdef /hungarumlaut /ogonek /caron /space] >> endobj 10 0 obj << /Type /Font /Subtype /Type1 /Name /F2 /BaseFont /Helvetica /Encoding 9 0 R >> endobj xref 0 11 0000000000 65535 f 0000000021 00000 n 0000000163 00000 n 0000000872 00000 n 0000000955 00000 n 0000001067 00000 n 0000001100 00000 n 0000000212 00000 n 0000000292 00000 n 0000003795 00000 n 0000004052 00000 n trailer << /Size 11 /Info 1 0 R /Root 2 0 R >> startxref 4149 %%EOF RProtoBuf/vignettes/figures/fig-SER.pdf0000644000176200001440000001750513164671414017516 0ustar liggesusers%PDF-1.4 %ρ\r 1 0 obj << /CreationDate (D:20171003062252) /ModDate (D:20171003062252) /Title (R Graphics Output) /Producer (R 3.4.2) /Creator (R) >> endobj 2 0 obj << /Type /Catalog /Pages 3 0 R >> endobj 7 0 obj << /Type /Page /Parent 3 0 R /Contents 8 0 R /Resources 4 0 R >> endobj 8 0 obj << /Length 3950 /Filter /FlateDecode >> stream x[O 律}D_hb=9l`׎N=RqRxJGJ/7}j{Ǹ"{[HuOy}{uۯlɕߝs}_^ճo6}{/wW _>{z=^%+4u/en{z=}=_o{ov[e%.,[&x7InKܛj ~7 {=Kѯؽmdm5o/67$ÇG ^+]Ƿ|˻|;" &v@eoUݯD;P-,>yic8i{\7,_v-i+^W--W8 Z8l;mkc @]v w:lX@!GOqw X[ q9¾G NB ?6dO+n[ 6R^ QVLNiebKQI+^*;tVB Iw y 65 V>%1RYBVp&W7\ $Nd+t3WjXz; q$mLZPNfV#[ ;SdPZDB gPDh#njosȌDkcZf}r^W㣛h%-K@;Z A ؕų=,^KOm|;<[m)D6."8ݴsNVtpyLU4 @]حhu+(  N$QZʭu@YZ:(eے2R_J ^R )!sKE{EV %dVs` .5Xt%̬WE, G5\[is9eZ-`TQL_iraZ-m'7cZ#) J.)s YaCX:b.۠!'< XRR=}]DIP8r g@X>Nۓ{gxܟl4B'Qt̟:\ kؿ8(nH~XGO^?>AMw7_mO~b{r,t{W|[d^@-׷g?|f{W_Gǁ^v=!XW&I&y3HՐ`dtyxwVи bUG8G8ɳΐyS(0Cz5 '60$I> P* 4X`D3C> U73ghJ v#"KI+m0.&Wd6EcMB!9;X{%wj9 ZJrY >\%kӐ fk`"uiaJQK^-XO3?xxRwZiOI_gV@^]YDo͓!+2< zj,wg}:-Ez\@t:˳d$06yCh'D<(I> ɮMüಽ3ȳ~EжtSKуP#*^K'yַP֣dc( p_8Y_gtpD4bBw˺{F okz> [CsKӑN?vjbDjRfy7NZzyu ; <[lC=b^Yߐ"kSX lg}aKD1 .Gd1 ;䓾 4 MnǀY+6|k=RJ_ゑTwI>_BtNW6aT'oY/fYH4v80ɳ͠)8apZQ\dPI>6FoeMc30'}IwD i Q9?'}I/()f%,0UA #}xozȳ<H YSaXIء_ہ|] nOq2זqXe/If ƒTEdabЯ8Y߾"jرcgV{b/Bb)ZOO0݋0yַgX.@yg})둁VB5d/7˳>g^,Gh ZWb^ VK>9ɳz5Zydf~RXtgg}NY+ͭl"Nfݴ//o>$ԼGMË&IGdieH, iC>XP| q=ttO~r95,%QpWZ2&r?Y0sVz\x=ˡY/uP%>E>GiUգZK2CGƉ{0)qi<>IA(tՇ< Y 5ٱ"Vqp6˳ij/r:OV_/Cx5`=[7x4mgчR8') |LUI쁈VV4'}  #?[E>`~ჷ<^ί:Y_VE{^@Z{&"ʡI-t9twMָg}Ruk%&$^R8YtY 6- ~҂X.?:9E-=#H?OurYRe܅kfعېO}QڋY"I}2:lo>شdY_K3d^vuV;7Z!գ_gNb&R2\|ҿ,ְE;M{- N['onQ#jp'/6z)5o4Do=QnI͎& iu8nM[y;IAu!/sZIQ`TSJ_E>N&e4_Gfeg}[%0|Kg2'} ibu7f嬵٨uo.?QNGF?jGé};ZE@+}{sȳ,:8F:Y8\uNN@:C>.לeڹ\?*f9mDMȻ6S4!0xl[.0$;P;nng/7xt';H|~9{wJ] hc7?\޼Cn)|f^߼n/ ._?'{=?ٕ0^VYGD-V WOt߶uO=-콉 ~?|}o߾vWW7endstream endobj 3 0 obj << /Type /Pages /Kids [ 7 0 R ] /Count 1 /MediaBox [0 0 432 432] >> endobj 4 0 obj << /ProcSet [/PDF /Text] /Font << /F1 10 0 R /F2 11 0 R >> /ExtGState << >> /ColorSpace << /sRGB 5 0 R >> >> endobj 5 0 obj [/ICCBased 6 0 R] endobj 6 0 obj << /Alternate /DeviceRGB /N 3 /Length 2596 /Filter /FlateDecode >> stream xwTSϽ7PkhRH H.*1 J"6DTpDQ2(C"QDqpId߼y͛~kg}ֺLX Xňg` lpBF|،l *?Y"1P\8=W%Oɘ4M0J"Y2Vs,[|e92<se'9`2&ctI@o|N6(.sSdl-c(2-yH_/XZ.$&\SM07#1ؙYrfYym";8980m-m(]v^DW~ emi]P`/u}q|^R,g+\Kk)/C_|Rax8t1C^7nfzDp 柇u$/ED˦L L[B@ٹЖX!@~(* {d+} G͋љς}WL$cGD2QZ4 E@@A(q`1D `'u46ptc48.`R0) @Rt CXCP%CBH@Rf[(t CQhz#0 Zl`O828.p|O×X ?:0FBx$ !i@ڐH[EE1PL ⢖V6QP>U(j MFkt,:.FW8c1L&ӎ9ƌaX: rbl1 {{{;}#tp8_\8"Ey.,X%%Gщ1-9ҀKl.oo/O$&'=JvMޞxǥ{=Vs\x ‰N柜>ucKz=s/ol|ϝ?y ^d]ps~:;/;]7|WpQoH!ɻVsnYs}ҽ~4] =>=:`;cܱ'?e~!ańD#G&}'/?^xI֓?+\wx20;5\ӯ_etWf^Qs-mw3+?~O~endstream endobj 9 0 obj << /Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences [ 45/minus 96/quoteleft 144/dotlessi /grave /acute /circumflex /tilde /macron /breve /dotaccent /dieresis /.notdef /ring /cedilla /.notdef /hungarumlaut /ogonek /caron /space] >> endobj 10 0 obj << /Type /Font /Subtype /Type1 /Name /F1 /BaseFont /ZapfDingbats >> endobj 11 0 obj << /Type /Font /Subtype /Type1 /Name /F2 /BaseFont /Helvetica /Encoding 9 0 R >> endobj xref 0 12 0000000000 65535 f 0000000021 00000 n 0000000163 00000 n 0000004314 00000 n 0000004397 00000 n 0000004521 00000 n 0000004554 00000 n 0000000212 00000 n 0000000292 00000 n 0000007249 00000 n 0000007506 00000 n 0000007590 00000 n trailer << /Size 12 /Info 1 0 R /Root 2 0 R >> startxref 7687 %%EOF RProtoBuf/vignettes/figures/protobuf-distributed-system-crop.pdf0000644000176200001440000002565013005133352024751 0ustar liggesusers%PDF-1.4 % 5 0 obj << /Length 38 /Filter /FlateDecode >> stream x+2T0BC]s#]3\.}\C|@.f6 endstream endobj 4 0 obj << /Type /Page /Contents 5 0 R /Resources 3 0 R /MediaBox [0 0 468 119] /Parent 6 0 R /Group 2 0 R >> endobj 1 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./protobuf-distributed-system.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 7 0 R /BBox [0 0 611.999983 791.999983] /Group 2 0 R /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >>/Font << /f-0-0 8 0 R>> >> /Length 894 /Filter /FlateDecode >> stream xVK1 W`;oiBBT8v B,pc5S^t2c;/nCb3l7C?>=§!"A*s( Nu KrK$/bGCU͍VFwM o0C`1gOu#a=ۙbCJ$!h~d)C^rݝyzd߈ao7(OR*O6`gu?SYVs???^آnr-ۮ+>uٟi1uAIr;*MGԍ J xYƮN{4ss7 2 (K}7Z ^U;:44~[<9(0z[vF+ɲ Ko2rq$',cʂYnI6!pOVuhMRzBNUgt;uuo2] cZqeXP#r0tu`3RvE8h|Gŏ!b HY"ls!0D"qFJ"1S)2yKgd8UQѥ4' bo,% i36aR8,]YI ~|ۿZP^Dz>Q=dؿ'iH@ :U,*2hrd,DGet dZ*ٲW .v}:.Ǯ$DRCpfqSvg#{IsA9"/g<ίD(ܬN衺7MC0X,\&_pUGC,&.(ݴdi֌vF2DW0q>Ɣ0 }jII^W endstream endobj 7 0 obj << /Creator (cairo 1.10.2 \(http://cairographics.org\)) /Producer (cairo 1.10.2 \(http://cairographics.org\)) >> endobj 8 0 obj << /Type /Font /Subtype /Type0 /BaseFont /LSNSMW+DejaVuSans /Encoding /Identity-H /DescendantFonts [ 9 0 R] /ToUnicode 10 0 R >> endobj 9 0 obj << /Type /Font /Subtype /CIDFontType2 /BaseFont /LSNSMW+DejaVuSans /CIDSystemInfo << /Registry (Adobe) /Ordering (Identity) /Supplement 0 >> /FontDescriptor 11 0 R /W [ 0 [ 600 634 615 633 634 520 317 411 634 633 392 352 611 612 774 633 277 336 634 634 277 294 549 591 694 770 988 684 817 634 603 787 610 591 974 524 748 579]] >> endobj 10 0 obj << /Length 12 0 R /Filter /FlateDecode >> stream x]j0>Eâɪe{?b2n%߾1 G&yn찲M54M`fkգ'۲~J>nc'3u07g _ђ -䔽RReYNȚDZorgYq@e:rPHƼ2@1zqwPX%Hz*(@<ipIɣ _ ~%lyC~EF~'c,E__;I)/i ]8}F}sba,o<{Vx" endstream endobj 11 0 obj << /Type /FontDescriptor /FontName /LSNSMW+DejaVuSans /FontFamily (DejaVu Sans) /Flags 4 /FontBBox [ -1020 -415 1680 1166] /ItalicAngle 0 /Ascent 928 /Descent -235 /CapHeight 1166 /StemV 80 /StemH 80 /FontFile2 13 0 R >> endobj 12 0 obj 382 endobj 13 0 obj << /Length 14 0 R /Filter /FlateDecode /Length1 9936 >> stream xzy|TU{}ƚN*P*!H:!@E A "@0`>aFdjHcjAUW|Dii/N!ٹT%}M߫33ַuPBNjUgI3/@H*"$A= IsU,n[w̡sm\cM lE|ǯH'_}l).c4 س76ح79ֿ} (ze}!R9) @#r 9uT2ΩH#"#whŖ6Ӌs]f?Ӟ<(_Mm/T׎`l>V*7n_,$AV\|q!F"*ezIacmvמy˒k&w^HcaDS_td ~a.u| Ǟ{≝;x98nmg4: &ϝ;+cNY8"纱=.C,uo.ɔؾ1Au)/mD/OG ҕn{~8-{M݉zcq цC!#@4{r}ѽ{dS3ˌeeN/:eLeq (%iYòoˮή~,{kةOA$ v\W7}ݰgͯUqtëf<;az*-Ƥzot0=HacK7M&op$yO6bP i͊.DfO7 ;PDm2bດ1}6=4Ҩ~pk?ҹAV1sY1I3gW[ pkM{UXƏ"^H󴶆v|EY_.zb 4_le Xn7:]ݿop+ri/0Gm"i5 _0 C!b߯1IaP&}b;:mrd;uoŌ Ӟh|3ڀv6Xx]6 m|͹m4EEyS;Shǎ т.UbyV[7Z7nYzuQd=ԡi-YuEm\ݏmK'7LZmt^4%lV7lWk~f|<ɣ-N8cIԶ0ݶ3q 4WظP2kƚ\xo͸t0nbuV%MwUuDl/݁HIWEjZ֪jQvU=fwk܅8mOOl޺{ݻ!&|zc_oo6-{ c m6$H#Fs]1r ,K9ؔ 1kx hSt3찖֋m{ΛEfKKK ˲d+ XVZIRIrIJI$$$2kiRmrmJm6uicY[.d%]Io}*s*;V[5;OwtVOH7л=tv[xG'ɯ8|C"qxe667Xun1na@^"E‘;,[J~H6H1B6YUl_G),-! -x-:%ty7?$CӞ_肐k= I FH## ~_300</T ]]'^`םd}w4,~ƥyGDØێ~2"'ra(WX׭[F\ifbǖG/[8Ln¾h bc# qJd8GLxd*KtBR٥k{N{iD`Y~R=D=*9I&y~TJmQan.`jxڋqQLA%bϽƢCcvF<(¸Nw*k kRAn 0pU9⪪pvgG@7Tk%D6jpԉ0x&c%~Gze29Q^j_ӯg7bҧ eż ')Dc*I@P$,h;+_sx\)Pӵ =h\P6 Њa<'1KtT,+ŪZp\$uUnit^&)ejV -}|HYV Վj2V 1j+5[z&:M~EgIQ'/k{_Ǔs[AM¼CMtb2+&dQ3AW z icP'h\7<"3Վ_g_9Q==iG8܊[u~RIVM*&E86Nf%,ýeZKǓl4H1THg< /Y;o[~:`_{q; AANv"vۉG}_f䱍f-c&RYmt NsN.΢Y4O 1l Ⱦ'%=^/Bt/Btײ INofv Ii KUCÝ Z j3YJA&)A5 j;`4@-FHɒ%[Gl7ll9a+uVO4fr:͆l>[ܣM3nwq'"JK0WT(8jJXe9bZ$=mFݠZ -dζi%Rϻ^f륭17z/IwYTt2CYZp|RfQd70"Xy5"iZ5'a^S{#UU<05ʺ|iwM.XiX@.dl^c#G0񨑧xdr. {YU6dZv.mȵ䷘V2(6F6b!AQ(R {GZ&f2VeRV5Fԩ~Y!M ;g:3 `,kdvo J-,W9*8( PT1lQwTH+ʐÖ!y e4*`-$c$c#D'3"y)]!Ӎ菛Zą-Rs/tCلNlN1eUf^9da9ns= *l'nF,sI U:-:5 Tt Ksr̂2G,EUZ^lnxTP>T~ tA:N,8CM,M>vcMzb^IXY 6⳿?H.r!Յ[!wȶ_f-U]yAEܨYM h'XǓH2I~R1>I!RHB8.d݁g\ld>N:vQ8FS#JGwQ-BKqF)$N?\.ҥh&(#kg n/U&_Ket|FQiu1 K-&uR.>oP d6U}d? d )<^y $}c^CWINIt} XD94FkSRӀG 4F@d4FR0[299bx[G Ƕ >fl1<|oLYc`Ƭ ϊ+<3D+}ȉ>@RpHߵnu;9&Jzb"?}>yow_&"HFr/9s2+r d\K~Td}?+"aϾ7rT5MR&"WI>>gT@&|v͋pP<[!WH5+V1$PJ/\O&DJk)xlX 3Q@v 09D}џ8^@0'\/`,^+1~]Ir1QF6.Z֗_/5c0LWy>j_兡C|!N,H>>>Ph(428!w;r \x?ՠO>r彃^YA Bfn! ]@Rq^CJ;$! D _ qx' bS18 LY %.#;8nG4thTM@. /J?`+2@C|jÏ6KON? endstream endobj 14 0 obj 7258 endobj 2 0 obj << /Type /Group /S /Transparency /CS /DeviceRGB >>endobj 3 0 obj << /XObject << /Im1 1 0 R >> /ProcSet [ /PDF ] >> endobj 6 0 obj << /Type /Pages /Count 1 /Kids [4 0 R] >> endobj 15 0 obj << /Type /Catalog /Pages 6 0 R >> endobj 16 0 obj << /Producer (pdfTeX-1.40.10) /Creator (TeX) /CreationDate (D:20140103113848-08'00') /ModDate (D:20140103113848-08'00') /Trapped /False /PTEX.Fullbanner (This is pdfTeX, Version 3.1415926-1.40.10-2.2 (TeX Live 2009/Debian) kpathsea version 5.0.0) >> endobj xref 0 17 0000000000 65535 f 0000000250 00000 n 0000010176 00000 n 0000010241 00000 n 0000000133 00000 n 0000000016 00000 n 0000010306 00000 n 0000001475 00000 n 0000001603 00000 n 0000001747 00000 n 0000002092 00000 n 0000002550 00000 n 0000002787 00000 n 0000002807 00000 n 0000010155 00000 n 0000010363 00000 n 0000010413 00000 n trailer << /Size 17 /Root 15 0 R /Info 16 0 R /ID [ ] >> startxref 10679 %%EOF RProtoBuf/vignettes/figures/fig-021.pdf0000644000176200001440000001052713005133352017350 0ustar liggesusers%PDF-1.4 %ρ\r 1 0 obj << /CreationDate (D:20160710174714) /ModDate (D:20160710174714) /Title (R Graphics Output) /Producer (R 3.3.1) /Creator (R) >> endobj 2 0 obj << /Type /Catalog /Pages 3 0 R >> endobj 7 0 obj << /Type /Page /Parent 3 0 R /Contents 8 0 R /Resources 4 0 R >> endobj 8 0 obj << /Length 501 /Filter /FlateDecode >> stream xMo0 <&$ڠ`ú!HAI~-Y~RIQݸbOo/awb9O]\K~[%Hw÷=_K\?c__=TkvUIUoҸe{^P}n+V6&`=-XDp--Zl~Ý2eG(yL\jJ<Y>IY4)~O".-ݖywϋ7nF%O^E"Y"y4߫%!9%r[pEj˶C,*QU̸Ɍ9dƭNfda;gqI5 |&.mI*Gḷm6m"Gl\KYl woc Q۶NCZxbQQA8Iqf4=So/`JrHendstream endobj 3 0 obj << /Type /Pages /Kids [ 7 0 R ] /Count 1 /MediaBox [0 0 576 288] >> endobj 4 0 obj << /ProcSet [/PDF /Text] /Font <> /ExtGState << >> /ColorSpace << /sRGB 5 0 R >> >> endobj 5 0 obj [/ICCBased 6 0 R] endobj 6 0 obj << /Alternate /DeviceRGB /N 3 /Length 2596 /Filter /FlateDecode >> stream xwTSϽ7PkhRH H.*1 J"6DTpDQ2(C"QDqpId߼y͛~kg}ֺLX Xňg` lpBF|،l *?Y"1P\8=W%Oɘ4M0J"Y2Vs,[|e92<se'9`2&ctI@o|N6(.sSdl-c(2-yH_/XZ.$&\SM07#1ؙYrfYym";8980m-m(]v^DW~ emi]P`/u}q|^R,g+\Kk)/C_|Rax8t1C^7nfzDp 柇u$/ED˦L L[B@ٹЖX!@~(* {d+} G͋љς}WL$cGD2QZ4 E@@A(q`1D `'u46ptc48.`R0) @Rt CXCP%CBH@Rf[(t CQhz#0 Zl`O828.p|O×X ?:0FBx$ !i@ڐH[EE1PL ⢖V6QP>U(j MFkt,:.FW8c1L&ӎ9ƌaX: rbl1 {{{;}#tp8_\8"Ey.,X%%Gщ1-9ҀKl.oo/O$&'=JvMޞxǥ{=Vs\x ‰N柜>ucKz=s/ol|ϝ?y ^d]ps~:;/;]7|WpQoH!ɻVsnYs}ҽ~4] =>=:`;cܱ'?e~!ańD#G&}'/?^xI֓?+\wx20;5\ӯ_etWf^Qs-mw3+?~O~endstream endobj 9 0 obj << /Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences [ 45/minus 96/quoteleft 144/dotlessi /grave /acute /circumflex /tilde /macron /breve /dotaccent /dieresis /.notdef /ring /cedilla /.notdef /hungarumlaut /ogonek /caron /space] >> endobj 10 0 obj << /Type /Font /Subtype /Type1 /Name /F2 /BaseFont /Helvetica /Encoding 9 0 R >> endobj xref 0 11 0000000000 65535 f 0000000021 00000 n 0000000163 00000 n 0000000864 00000 n 0000000947 00000 n 0000001059 00000 n 0000001092 00000 n 0000000212 00000 n 0000000292 00000 n 0000003787 00000 n 0000004044 00000 n trailer << /Size 11 /Info 1 0 R /Root 2 0 R >> startxref 4141 %%EOF RProtoBuf/vignettes/RProtoBuf-paper.Rnw0000644000176200001440000017477613005133352017644 0ustar liggesusers\documentclass[article,nojss]{jss} %\VignetteIndexEntry{RProtoBuf-paper} %\VignetteKeywords{RProtoBuf, Protocol Buffers, package} %\VignetteDepends{RProtoBuf} \usepackage{thumbpdf,listings,booktabs} \graphicspath{{figures/}} \shortcites{sciencecloud,janus,dremel,nlme} \DefineVerbatimEnvironment{example}{Verbatim}{} % Line numbers for drafts. %\usepackage[switch, modulo]{lineno} %\linenumbers %%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Spelling Standardization: % Protocol Buffers, not protocol buffers % large-scale, not large scale % Oxford comma: foo, bar, and baz. % Articles with many authors we should shorten to FirstAuthor, et al. \author{Dirk Eddelbuettel\\Debian Project \And Murray Stokely\\Google, Inc \And Jeroen Ooms\\University of California,\\Los Angeles} \Plainauthor{Dirk Eddelbuettel, Murray Stokely, Jeroen Ooms} \title{\pkg{RProtoBuf}: Efficient Cross-Language Data Serialization in \proglang{R}} \Plaintitle{RProtoBuf: Efficient Cross-Language Data Serialization in R} \Shorttitle{\pkg{RProtoBuf}: Protocol Buffers in \proglang{R}} %% an abstract and keywords \Abstract{ Modern data collection and analysis pipelines often involve a sophisticated mix of applications written in general purpose and specialized programming languages. Many formats commonly used to import and export data between different programs or systems, such as CSV or JSON, are verbose, inefficient, not type-safe, or tied to a specific programming language. Protocol Buffers are a popular method of serializing structured data between applications -- while remaining independent of programming languages or operating systems. They offer a unique combination of features, performance, and maturity that seems particularly well suited for data-driven applications and numerical computing. The \pkg{RProtoBuf} package provides a complete interface to Protocol Buffers from the \proglang{R} environment for statistical computing. This paper outlines the general class of data serialization requirements for statistical computing, describes the implementation of the \pkg{RProtoBuf} package, and illustrates its use with example applications in large-scale data collection pipelines and web services. } \Keywords{\proglang{R}, \pkg{Rcpp}, Protocol Buffers, serialization, cross-platform} \Plainkeywords{R, Rcpp, Protocol Buffers, serialization, cross-platform} \Volume{71} \Issue{2} \Month{July} \Year{2016} \Submitdate{2014-02-05} \Acceptdate{2015-04-13} %\DOI{10.18637/jss.v071.i02} %% The address of (at least) one author should be given %% in the following format: \Address{ Dirk Eddelbuettel \\ Debian Project \\ River Forest, IL, United States of America\\ E-mail: \email{edd@debian.org}\\ URL: \url{http://dirk.eddelbuettel.com/}\\ Murray Stokely\\ Google, Inc.\\ 1600 Amphitheatre Parkway\\ Mountain View, CA, United States of America\\ E-mail: \email{murray@stokely.org}\\ URL: \url{http://www.stokely.org/}\\ Jeroen Ooms\\ UCLA Department of Statistics\\ University of California, Los Angeles\\ Los Angeles, CA, United States of America\\ E-mail: \email{jeroen.ooms@stat.ucla.edu}\\ URL: \url{https://jeroenooms.github.io/} } %% It is also possible to add a telephone and fax number %% before the e-mail in the following format: %% Telephone: +43/512/507-7103 %% Fax: +43/512/507-2851 %% for those who use Sweave please include the following line (with % symbols): %% need no \usepackage{Sweave.sty} %% end of declarations %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% <>= library(RProtoBuf) rprotobuf.version <- packageDescription("RProtoBuf")$Version rprotobuf.date <- packageDescription("RProtoBuf")$Date now.date <- strftime(Sys.Date(), "%B %d, %Y") @ \begin{document} \SweaveOpts{concordance=FALSE,prefix.string=figures/fig} %% include your article here, just as usual %% Note that you should use the \pkg{}, \proglang{} and \code{} commands. % We don't want a left margin for Sinput or Soutput for our table 1. %\DefineVerbatimEnvironment{Sinput}{Verbatim} {xleftmargin=0em} %\DefineVerbatimEnvironment{Soutput}{Verbatim}{xleftmargin=0em} %\DefineVerbatimEnvironment{Scode}{Verbatim}{xleftmargin=2em} % Setting the topsep to 0 reduces spacing from input to output and % improves table 1. \fvset{listparameters={\setlength{\topsep}{0pt}}} \renewenvironment{Schunk}{\vspace{\topsep}}{\vspace{\topsep}} %% DE: I tend to have wider option(width=...) so this %% guarantees better line breaks <>= ## cf http://www.jstatsoft.org/style#q12 options(prompt = "R> ", continue = "+ ", width = 70, useFancyQuotes = FALSE, digits = 4) @ \maketitle \section{Introduction} Modern data collection and analysis pipelines increasingly involve collections of decoupled components in order to better manage software complexity through reusability, modularity, and fault isolation \citep{Wegiel:2010:CTT:1932682.1869479}. These pipelines are frequently built using different programming languages for the different phases of data analysis -- collection, cleaning, modeling, analysis, post-processing, and presentation -- in order to take advantage of the unique combination of performance, speed of development, and library support offered by different environments and languages. Each stage of such a data analysis pipeline may produce intermediate results that need to be stored in a file, or sent over the network for further processing. Given these requirements, how do we safely and efficiently share intermediate results between different applications, possibly written in different languages, and possibly running on different computer systems? In computer programming, \emph{serialization} is the process of translating data structures, variables, and session states into a format that can be stored or transmitted and then later reconstructed in the original form \citep{clinec++}. Programming languages such as \proglang{R} \citep{r}, \proglang{Julia} \citep{julia}, \proglang{Java}, and \proglang{Python} \citep{python} include built-in support for serialization, but the default formats are usually language-specific and thereby lock the user into a single environment. Data analysts and researchers often use character-separated text formats such as CSV \citep{shafranovich2005common} to export and import data. However, anyone who has ever used CSV files will have noticed that this method has many limitations: It is restricted to tabular data, lacks type-safety, and has limited precision for numeric values. Moreover, ambiguities in the format itself frequently cause problems. For example, conventions on which characters are used as separator or decimal point vary by country. \emph{Extensible markup language} (XML) is a well-established and widely-supported format with the ability to define just about any arbitrarily complex schema \citep{nolan2013xml}. However, it pays for this complexity with comparatively large and verbose messages, and added complexity at the parsing side (these problems are somewhat mitigated by the availability of mature libraries and parsers). Because XML is text-based and has no native notion of numeric types or arrays, it is usually not a very practical format to store numeric data sets as they appear in statistical applications. A more modern format is \emph{\proglang{JavaScript} object notation} (JSON), which is derived from the object literals of \proglang{JavaScript}, and already widely-used on the world wide web. Several \proglang{R} packages implement functions to parse and generate JSON data from \proglang{R} objects \citep{rjson,RJSONIO,jsonlite}. JSON natively supports arrays and four primitive types: numbers, strings, booleans, and null. However, as it also is a text-based format, numbers are stored in human-readable decimal notation which is inefficient and leads to loss of type (double versus integer) and precision. A number of binary formats based on JSON have been proposed that reduce the parsing cost and improve efficiency, but these formats are not widely supported. Furthermore, such formats lack a separate schema for the serialized data and thus still duplicate field names with each message sent over the network or stored in a file. Once the data serialization needs of an application become complex enough, developers typically benefit from the use of an \emph{interface description language}, or \emph{IDL}. IDLs like Protocol Buffers \citep{protobuf}, Apache Thrift \citep{Apache:Thrift}, and Apache Avro \citep{Apache:Avro} provide a compact well-documented schema for cross-language data structures and efficient binary interchange formats. Since the schema is provided separately from the data, the data can be efficiently encoded to minimize storage costs when compared with simple ``schema-less'' binary interchange formats. %Many sources compare data serialization formats %and show Protocol Buffers perform favorably to the alternatives; see %\citet{Sumaray:2012:CDS:2184751.2184810} for one such comparison. Protocol Buffers perform well in the comparison of such formats by \citet{Sumaray:2012:CDS:2184751.2184810}. This paper describes an \proglang{R} interface to Protocol Buffers, and is organized as follows. Section~\ref{sec:protobuf} provides a general high-level overview of Protocol Buffers as well as a basic motivation for their use. Section~\ref{sec:rprotobuf-basic} describes the interactive \proglang{R} interface provided by the \pkg{RProtoBuf} package, and introduces the two main abstractions: \emph{Messages} and \emph{Descriptors}. Section~\ref{sec:rprotobuf-classes} details the implementation of the main \proglang{S}4 classes and methods. Section~\ref{sec:types} describes the challenges of type coercion between \proglang{R} and other languages. Section~\ref{sec:evaluation} introduces a general \proglang{R} language schema for serializing arbitrary \proglang{R} objects and compares it to the serialization capabilities built directly into \proglang{R}. Sections~\ref{sec:mapreduce} and \ref{sec:opencpu} provide real-world use cases of \pkg{RProtoBuf} in MapReduce and web service environments, respectively, before Section~\ref{sec:summary} concludes. \makeatletter \if@nojss This vignette corresponds to the paper published in the \textsl{Journal of Statistical Software}. For citations, please see the output of \proglang{R} function \texttt{citation("RProtoBuf")}. This version corresponds to \pkg{RProtoBuf} version \Sexpr{rprotobuf.version} and was typeset on \Sexpr{now.date}. \fi \makeatother \section{Protocol Buffers} \label{sec:protobuf} Protocol Buffers are a modern, language-neutral, platform-neutral, extensible mechanism for sharing and storing structured data. Some of their features, particularly in the context of data analysis, are: % \begin{itemize} \item \emph{Portable}: Enable users to send and receive data between applications as well as different computers or operating systems. \item \emph{Efficient}: Data is serialized into a compact binary representation for transmission or storage. \item \emph{Extensible}: New fields can be added to Protocol Buffer schemas in a forward-compatible way that does not break older applications. \item \emph{Stable}: Protocol Buffers have been in wide use for over a decade. \end{itemize} % \begin{figure}[t!] \centering \includegraphics[width=0.9\textwidth]{protobuf-distributed-system-crop.pdf} \caption{Example usage of Protocol Buffers.} \label{fig:protobuf-distributed-usecase} \end{figure} % Figure~\ref{fig:protobuf-distributed-usecase} illustrates an example communication work flow with Protocol Buffers and an interactive \proglang{R} session. Common use cases include populating a request remote-procedure call (RPC) Protocol Buffer in \proglang{R} that is then serialized and sent over the network to a remote server. The server deserializes the message, acts on the request, and responds with a new Protocol Buffer over the network. The key difference to, say, a request to an \pkg{Rserve} \citep{Urbanek:2003:Rserve,CRAN:Rserve} instance is that the remote server may be implemented in any language. %, with no dependence on \proglang{R}. While traditional IDLs have at times been criticized for code bloat and complexity, Protocol Buffers are based on a simple list and records model that is flexible and easy to use. The schema for structured Protocol Buffer data is defined in \code{.proto} files, which may contain one or more message types. Each message type has one or more fields. A field is specified with a unique number (called a \emph{tag number}), a name, a value type, and a field rule specifying whether the field is optional, required, or repeated. The supported value types are numbers, enumerations, booleans, strings, raw bytes, or other nested message types. The \code{.proto} file syntax for defining the structure of Protocol Buffer data is described comprehensively on Google Code at \url{http://code.google.com/apis/protocolbuffers/docs/proto.html}. Table~\ref{tab:proto} shows an example \code{.proto} file that defines the \code{tutorial.Person} type\footnote{The compound name \code{tutorial.Person} in \proglang{R} is derived from the name of the message (\emph{Person}) and the name of the package defined at the top of the \code{.proto} file in which it is defined (\emph{tutorial}).}. The \proglang{R} code in the right column shows an example of creating a new message of this type and populating its fields. \noindent \begin{table}[t!] \begin{tabular}{p{0.45\textwidth}p{0.5\textwidth}} \toprule Schema : \code{addressbook.proto} & Example \proglang{R} session\\ \cmidrule{1-2} \begin{minipage}{.40\textwidth} \vspace{2mm} \begin{example} package tutorial; message Person { required string name = 1; required int32 id = 2; optional string email = 3; enum PhoneType { MOBILE = 0; HOME = 1; WORK = 2; } message PhoneNumber { required string number = 1; optional PhoneType type = 2; } repeated PhoneNumber phone = 4; } \end{example} \vspace{2mm} \end{minipage} & \begin{minipage}{.55\textwidth} <>= library("RProtoBuf") p <- new(tutorial.Person, id=1, name="Dirk") p$name p$name <- "Murray" cat(as.character(p)) serialize(p, NULL) class(p) @ \end{minipage} \\ \bottomrule \end{tabular} \caption{The schema representation from a \code{.proto} file for the \code{tutorial.Person} class (left) and simple \proglang{R} code for creating an object of this class and accessing its fields (right).} \label{tab:proto} \end{table} For added speed and efficiency, the \proglang{C++}, \proglang{Java}, and \proglang{Python} bindings to Protocol Buffers are used with a compiler that translates a Protocol Buffer schema description file (ending in \code{.proto}) into language-specific classes that can be used to create, read, write, and manipulate Protocol Buffer messages. The \proglang{R} interface, in contrast, uses a reflection-based API that makes some operations slightly slower but which is much more convenient for interactive data analysis. All messages in \proglang{R} have a single class structure, but different accessor methods are created at runtime based on the named fields of the specified message type, as described in the next section. \section{Basic usage: Messages and descriptors} \label{sec:rprotobuf-basic} This section describes how to use the \proglang{R} API to create and manipulate Protocol Buffer messages in \proglang{R}, and how to read and write the binary representation of the message (often called the \emph{payload}) to files and arbitrary binary \proglang{R} connections. The two fundamental building blocks of Protocol Buffers are \emph{Messages} and \emph{Descriptors}. Messages provide a common abstract encapsulation of structured data fields of the type specified in a Message Descriptor. Message Descriptors are defined in \code{.proto} files and define a schema for a particular named class of messages. \subsection[Importing Message Descriptors from .proto files]{Importing Message Descriptors from \code{.proto} files} To create or parse a Protocol Buffer message, one must first read in the Message Descriptor (\emph{message type}) from a \code{.proto} file. A small number of message types are imported when the package is first loaded, including the \code{tutorial.Person} type we saw in the last section. All other types must be imported from \code{.proto} files using the \code{readProtoFiles} function, which can either import a single file, all files in a directory, or every \code{.proto} file provided by a particular \proglang{R} package. After importing proto files, the corresponding Message Descriptors are available by name from the \code{RProtoBuf:DescriptorPool} environment in the \proglang{R} search path. This environment is implemented with the user-defined tables framework from the \pkg{RObjectTables} package available from the OmegaHat project \citep{RObjectTables}. Instead of being associated with a static hash table, this environment dynamically queries the in-memory database of loaded descriptors during normal variable lookup. This allows new descriptors to be parsed from \code{.proto} files and added to the global namespace.\footnote{Note that there is a significant performance overhead with this \pkg{RObjectTables} implementation. Because the table is on the search path and is not cacheable, lookups of symbols that are behind it in the search path cannot be added to the global object cache, and \proglang{R} must perform an expensive lookup through all of the attached environments and the Protocol Buffer definitions to find common symbols (most notably those in base) from the global environment. Fortunately, proper use of namespaces and package imports reduces the impact of this for code in packages.} \subsection*{Creating, accessing, and modifying messages.} New messages are created with the \code{new} function which accepts a Message Descriptor and optionally a list of ``name = value'' pairs to set in the message. %The objects contained in the special environment are %descriptors for their associated message types. Descriptors will be %discussed in detail in another part of this document, but for the %purpose of this section, descriptors are just used with the \code{new} %function to create messages. <<>>= p <- new(tutorial.Person, name = "Murray", id = 1) @ % \subsection*{Access and modify fields of a message} Once the message is created, its fields can be queried and modified using the dollar operator of \proglang{R}, making Protocol Buffer messages seem like lists. <<>>= p$name p$id p$email <- "murray@stokely.org" @ As opposed to \proglang{R} lists, no partial matching is performed and the name must be given entirely. The \verb|[[| operator can also be used to query and set fields of a message, supplying either their name or their tag number: <<>>= p[["name"]] <- "Murray Stokely" p[[ 2 ]] <- 3 p[["email"]] @ Protocol Buffers include a 64-bit integer type, but \proglang{R} lacks native 64-bit integer support. A workaround is available and described in Section~\ref{sec:int64} for working with large integer values. \subsection*{Printing, reading, and writing Messages} % \textbf{Printing, Reading, and Writing Messages} Protocol Buffer messages and descriptors implement \code{show} methods that provide basic information about the message: <<>>= p @ %For additional information, such as for debugging purposes, The \code{as.character} method provides a more complete ASCII representation of the contents of a message. <<>>= writeLines(as.character(p)) @ % \subsection{Serializing messages} A primary benefit of Protocol Buffers is an efficient binary wire-format representation. The \code{serialize} method is implemented for Protocol Buffer messages to serialize a message into a sequence of bytes (raw vector) that represents the message. The raw bytes can then be parsed back into the original message safely as long as the message type is known and its descriptor is available. <<>>= serialize(p, NULL) @ The same method can be used to serialize messages to files or arbitrary binary connections: <<>>= tf1 <- tempfile() serialize(p, tf1) readBin(tf1, raw(0), 500) @ %\subsection{Parsing messages} The \pkg{RProtoBuf} package defines the \code{read} and \code{readASCII} functions to read messages from files, raw vectors, or arbitrary connections. \code{read} expects to read the message payload from binary files or connections and \code{readASCII} parses the human-readable ASCII output that is created with \code{as.character}. The binary representation of the message does not contain information that can be used to dynamically infer the message type, so we have to provide this information to the \code{read} function in the form of a descriptor: <<>>= msg <- read(tutorial.Person, tf1) writeLines(as.character(msg)) @ The \code{input} argument of \code{read} can also be a binary readable \proglang{R} connection, such as a binary file connection, or a raw vector of serialized bytes. \section{Under the hood: S4 classes and methods} \label{sec:rprotobuf-classes} The \pkg{RProtoBuf} package uses the \proglang{S}4 system to store information about descriptors and messages. Each \proglang{R} object contains an external pointer to an object managed by the \pkg{protobuf} \proglang{C++} library, and the \proglang{R} objects make calls into more than 100 \proglang{C++} functions that provide the glue code between the \proglang{R} language classes and the underlying \proglang{C++} classes. \proglang{S}4 objects are immutable, and so the methods that modify field values of a message return a new copy of the object with \proglang{R}'s usual functional copy on modify semantics\footnote{\pkg{RProtoBuf} was designed and implemented before Reference Classes were introduced to offer a new class system with mutable objects. If \pkg{RProtoBuf} were implemented today Reference Classes would almost certainly be a better design choice than \proglang{S}4 classes.}. Using the \proglang{S}4 system allows the package to dispatch methods that are not generic in the \proglang{S}3 sense, such as \code{new} and \code{serialize}. The \pkg{Rcpp} package \citep{eddelbuettel2011rcpp,eddelbuettel2013seamless} is used to facilitate this integration of the \proglang{R} and \proglang{C++} code for these objects. Each method is wrapped individually which allows us to add user-friendly custom error handling, type coercion, and performance improvements at the cost of a more verbose implementation. The \pkg{RProtoBuf} package in many ways motivated the development of \pkg{Rcpp} Modules \citep{eddelbuettel2013exposing}, which provide a more concise way of wrapping \proglang{C++} functions and classes in a single entity. Since \pkg{RProtoBuf} users are most often switching between two or more different languages as part of a larger data analysis pipeline, both generic function and message passing OO style calling conventions are supported: \begin{itemize} \item The functional dispatch mechanism of the the form \verb|method(object, arguments)| (common to \proglang{R}). \item The message passing object-oriented notation of the form \verb|object$method(arguments)|. \end{itemize} Additionally, \pkg{RProtoBuf} supports tab completion for all classes. Completion possibilities include method names for all classes, plus \emph{dynamic dispatch} on names or types specific to a given object. This functionality is implemented with the \code{.DollarNames} S3 generic function defined in the \pkg{utils} package that is included with \proglang{R} \citep{r}. Table~\ref{class-summary-table} lists the six primary message and descriptor classes in \pkg{RProtoBuf}. The package documentation provides a complete description of the slots and methods for each class. % [bp] \begin{table}[t!] \centering \begin{tabular}{lccl} \hline Class & Slots & Methods & Dynamic dispatch\\ \hline `\code{Message}' & 2 & 20 & yes (field names)\\ `\code{Descriptor}' & 2 & 16 & yes (field names, enum types, nested types)\\ `\code{FieldDescriptor}' & 4 & 18 & no\\ `\code{EnumDescriptor}' & 4 & 11 & yes (enum constant names)\\ `\code{EnumValueDescriptor}' & 3 & \phantom{1}6 & no\\ `\code{FileDescriptor}' & 3 & \phantom{1}6 & yes (message/field definitions)\\ \hline \end{tabular} \caption{\label{class-summary-table}Overview of class, slot, method and dispatch relationships.} \end{table} \subsection{Messages} The `\code{Message}' \proglang{S}4 class represents Protocol Buffer messages and is the core abstraction of \pkg{RProtoBuf}. Each `\code{Message}' contains a pointer to a `\code{Descriptor}' which defines the schema of the data defined in the message, as well as a number of `\code{FieldDescriptor}'s for the individual fields of the message. <<>>= new(tutorial.Person) @ \subsection{Descriptors} Descriptors describe the type of a message. This includes what fields a message contains and what the types of those fields are. Message descriptors are represented in \proglang{R} by the `\code{Descriptor}' \proglang{S}4 class. The class contains the slots \code{pointer} and \code{type}. Similarly to messages, the \verb|$| operator can be used to retrieve descriptors that are contained in the descriptor, or invoke methods. When \pkg{RProtoBuf} is first loaded it calls \code{readProtoFiles} which reads in the example file \code{addressbook.proto} included with the package. The \code{tutorial.Person} descriptor and all other descriptors defined in the loaded \code{.proto} files are then available on the search path\footnote{This explains why the example in Table~\ref{tab:proto} lacked an explicit call to \code{readProtoFiles}.}. \subsubsection*{Field descriptors} \label{subsec-field-descriptor} <<>>= tutorial.Person$email tutorial.Person$email$is_required() tutorial.Person$email$type() tutorial.Person$email$as.character() class(tutorial.Person$email) @ \subsubsection*{Enum and EnumValue descriptors} \label{subsec-enum-descriptor} The \code{EnumDescriptor} type contains information about what values a type defines, while the \code{EnumValueDescriptor} describes an individual enum constant of a particular type. The \verb|$| operator can be used to retrieve the value of enum constants contained in the EnumDescriptor, or to invoke methods. <<>>= tutorial.Person$PhoneType tutorial.Person$PhoneType$WORK class(tutorial.Person$PhoneType) tutorial.Person$PhoneType$value(1) tutorial.Person$PhoneType$value(name="HOME") tutorial.Person$PhoneType$value(number=1) class(tutorial.Person$PhoneType$value(1)) @ \subsubsection*{File descriptors} \label{subsec-file-descriptor} The class `\code{FileDescriptor}' represents file descriptors in \proglang{R}. The \verb|$| operator can be used to retrieve named fields defined in the `\code{FileDescriptor}', or to invoke methods. % < < > > = % f <- tutorial.Person$fileDescriptor() % f % f$Person % @ \begin{Schunk} \begin{Sinput} R> f <- tutorial.Person$fileDescriptor() R> f \end{Sinput} \begin{Soutput} file descriptor for package tutorial \ (/usr/local/lib/R/site-library/RProtoBuf/proto/addressbook.proto) \end{Soutput} \begin{Sinput} R> f$Person \end{Sinput} \begin{Soutput} descriptor for type 'tutorial.Person' \end{Soutput} \end{Schunk} \section{Type coercion} \label{sec:types} One of the benefits of using an interface definition language (IDL) like Protocol Buffers is that it provides a highly portable basic type system. This permits different language and hardware implementations to map to the most appropriate type in different environments. Table~\ref{table-get-types} details the correspondence between the field type and the type of data that is retrieved by \verb|$| and \verb|[[| extractors. Three types in particular need further attention due to specific differences in the \proglang{R} language: booleans, unsigned integers, and 64-bit integers. \begin{table}[t!] \centering \begin{small} \begin{tabular}{lp{5cm}p{5.5cm}} \toprule Field type & \proglang{R} type (non repeated) & \proglang{R} type (repeated) \\ \cmidrule(r){2-3} double & \code{double} vector & \code{double} vector \\ float & \code{double} vector & \code{double} vector \\[3mm] uint32 & \code{double} vector & \code{double} vector \\ fixed32 & \code{double} vector & \code{double} vector \\[3mm] int32 & \code{integer} vector & \code{integer} vector \\ sint32 & \code{integer} vector & \code{integer} vector \\ sfixed32 & \code{integer} vector & \code{integer} vector \\[3mm] int64 & \code{integer} or \code{character} vector & \code{integer} or \code{character} vector \\ uint64 & \code{integer} or \code{character} vector & \code{integer} or \code{character} vector \\ sint64 & \code{integer} or \code{character} vector & \code{integer} or \code{character} vector \\ fixed64 & \code{integer} or \code{character} vector & \code{integer} or \code{character} vector \\ sfixed64 & \code{integer} or \code{character} vector & \code{integer} or \code{character} vector \\[3mm] bool & \code{logical} vector & \code{logical} vector \\[3mm] string & \code{character} vector & \code{character} vector \\ bytes & \code{character} vector & \code{character} vector \\[3mm] enum & \code{integer} vector & \code{integer} vector \\[3mm] message & \code{S4} object of class \code{Message} & \code{list} of \code{S4} objects of class \code{Message} \\ \bottomrule \end{tabular} \end{small} \caption{\label{table-get-types}Correspondence between field type and \proglang{R} type retrieved by the extractors. \proglang{R} lacks native 64-bit integers, so the \code{RProtoBuf.int64AsString} option is available to return large integers as characters to avoid losing precision; see Section~\ref{sec:int64} below. All but the \code{Message} type can be represented in vectors of one or more elements; for the latter a list is used.} \end{table} \subsection{Booleans} \proglang{R} booleans can accept three values: \code{TRUE}, \code{FALSE}, and \code{NA}. However, most other languages, including the Protocol Buffer schema, only accept \code{TRUE} or \code{FALSE}. This means that we simply can not store \proglang{R} logical vectors that include all three possible values as booleans. The library will refuse to store \code{NA}s in Protocol Buffer boolean fields, and users must instead choose another type (such as enum or integer) capable of storing three distinct values. <>= if (!exists("JSSPaper.Example1", "RProtoBuf:DescriptorPool")) { readProtoFiles(file="proto/int64.proto") } @ % We want a cleaner error message here. \begin{CodeChunk} \begin{CodeInput} R> a <- new(JSSPaper.Example1) R> a$optional_bool <- TRUE R> a$optional_bool <- FALSE R> a$optional_bool <- NA \end{CodeInput} \begin{CodeOutput} Error: NA boolean values can not be stored in bool Protocol Buffer fields \end{CodeOutput} \end{CodeChunk} \subsection{Unsigned integers} \proglang{R} lacks a native unsigned integer type. Values between $2^{31}$ and $2^{32} - 1$ read from unsigned integer Protocol Buffer fields must be stored as doubles in \proglang{R}. <<>>= as.integer(2^31-1) as.integer(2^31 - 1) + as.integer(1) 2^31 class(2^31) @ \subsection{64-bit integers} \label{sec:int64} \proglang{R} also does not support the native 64-bit integer type. Numeric vectors with integer values greater or equal to $2^{31}$ can only be stored as floating-point double precision variables. This conversion incurs a loss of precision, and \proglang{R} loses the ability to distinguish between some distinct integer variables: <<>>= 2^53 == (2^53 + 1) @ Most modern languages do have support for 64-bit integer values, which becomes problematic when \pkg{RProtoBuf} is used to exchange data with a system that requires this integer type. To work around this, \pkg{RProtoBuf} allows users to get and set 64-bit integer values by specifying them as character strings. On 64-bit platforms, character strings representing large decimal numbers will be coerced to \code{int64} during assignment to 64-bit Protocol Buffer types to work around the lack of native 64-bit types in \proglang{R} itself. The values are stored as distinct \code{int64} values in memory. But when accessed from \proglang{R} language code, they will be coerced into numeric (floating-point) values. If the full 64-bit precision is required, the \code{RProtoBuf.int64AsString} option can be set to \code{TRUE} to return \code{int64} values from messages as character strings. Such character values are useful because they can accurately be used as unique identifiers, and can easily be passed to \proglang{R} packages such as \pkg{int64} \citep{int64} or \pkg{bit64} \citep{bit64} which represent 64-bit integers in \proglang{R}. \section[Converting R data structures into Protocol Buffers]{Converting \proglang{R} data structures into Protocol Buffers} \label{sec:evaluation} The previous sections discussed functionality in the \pkg{RProtoBuf} package for creating, manipulating, parsing, and serializing Protocol Buffer messages of a defined schema. This is useful when there are pre-existing systems with defined schemas or significant software components written in other languages that need to be accessed from within \proglang{R}. The package also provides methods for converting arbitrary \proglang{R} data structures into Protocol Buffers and vice versa with a universal \proglang{R} object schema. The \code{serialize\_pb} and \code{unserialize\_pb} functions serialize arbitrary \proglang{R} objects into a universal Protocol Buffer message: <<>>= msg <- serialize_pb(iris, NULL) identical(iris, unserialize_pb(msg)) @ In order to accomplish this, \pkg{RProtoBuf} uses the same catch-all \code{proto} schema used by \pkg{RHIPE} for exchanging \proglang{R} data with Hadoop \citep{rhipe}. This schema, which we will refer to as \code{rexp.proto}, is printed in %appendix \ref{rexp.proto}. the appendix. The Protocol Buffer messages generated by \pkg{RProtoBuf} and \pkg{RHIPE} are naturally compatible between the two systems because they use the same schema. This shows the power of using a schema-based cross-platform format such as Protocol Buffers: interoperability is achieved without effort or close coordination. The \code{rexp.proto} schema natively supports all main \proglang{R} storage types holding \emph{data}. These include \code{NULL}, \code{list} and vectors of type \code{logical}, \code{character}, \code{double}, \code{integer}, and \code{complex}. In addition, every type can contain a named set of attributes, as is the case in \proglang{R}. The storage types \code{function}, \code{language}, and \code{environment} are specific to \proglang{R} and have no equivalent native type in Protocol Buffers. These three types are supported by first serializing with \code{base::serialize} in \proglang{R} and then stored in a raw bytes field. \subsection[Evaluation: Serializing R data sets]{Evaluation: Serializing \proglang{R} data sets} \label{sec:compression} <>= datasets <- as.data.frame(data(package="datasets")$results) datasets$name <- sub("\\s+.*$", "", datasets$Item) n <- nrow(datasets) @ This section evaluates the effectiveness of serializing arbitrary \proglang{R} data structures into Protocol Buffers. We use the \Sexpr{n} standard data sets included in the \pkg{datasets} package included with \proglang{R} as our evaluation data. These data sets include data frames, matrices, time series, tables, lists, and some more exotic data classes. For each data set, we compare how many bytes are used to store the data set using four different methods: \begin{itemize} \item normal \proglang{R} serialization \citep{serialization}, \item \proglang{R} serialization followed by gzip, \item normal Protocol Buffer serialization, and \item Protocol Buffer serialization followed by gzip. \end{itemize} <>= datasets$object.size <- unname(sapply(datasets$name, function(x) object.size(eval(as.name(x))))) datasets$R.serialize.size <- unname(sapply(datasets$name, function(x) length(serialize(eval(as.name(x)), NULL)))) datasets$R.serialize.size <- unname(sapply(datasets$name, function(x) length(serialize(eval(as.name(x)), NULL)))) datasets$R.serialize.size.gz <- unname(sapply(datasets$name, function(x) length(memCompress(serialize(eval(as.name(x)), NULL), "gzip")))) datasets$RProtoBuf.serialize.size <- unname(sapply(datasets$name, function(x) length(serialize_pb(eval(as.name(x)), NULL)))) datasets$RProtoBuf.serialize.size.gz <- unname(sapply(datasets$name, function(x) length(memCompress(serialize_pb(eval(as.name(x)), NULL), "gzip")))) clean.df <- data.frame(dataset=datasets$name, object.size=datasets$object.size, "serialized"=datasets$R.serialize.size, "gzipped serialized"=datasets$R.serialize.size.gz, "RProtoBuf"=datasets$RProtoBuf.serialize.size, "gzipped RProtoBuf"=datasets$RProtoBuf.serialize.size.gz, "ratio.serialized" = datasets$R.serialize.size / datasets$object.size, "ratio.rprotobuf" = datasets$RProtoBuf.serialize.size / datasets$object.size, "ratio.serialized.gz" = datasets$R.serialize.size.gz / datasets$object.size, "ratio.rprotobuf.gz" = datasets$RProtoBuf.serialize.size.gz / datasets$object.size, "savings.serialized" = 1-(datasets$R.serialize.size / datasets$object.size), "savings.rprotobuf" = 1-(datasets$RProtoBuf.serialize.size / datasets$object.size), "savings.serialized.gz" = 1-(datasets$R.serialize.size.gz / datasets$object.size), "savings.rprotobuf.gz" = 1-(datasets$RProtoBuf.serialize.size.gz / datasets$object.size), check.names=FALSE) all.df<-data.frame(dataset="TOTAL", object.size=sum(datasets$object.size), "serialized"=sum(datasets$R.serialize.size), "gzipped serialized"=sum(datasets$R.serialize.size.gz), "RProtoBuf"=sum(datasets$RProtoBuf.serialize.size), "gzipped RProtoBuf"=sum(datasets$RProtoBuf.serialize.size.gz), "ratio.serialized" = sum(datasets$R.serialize.size) / sum(datasets$object.size), "ratio.rprotobuf" = sum(datasets$RProtoBuf.serialize.size) / sum(datasets$object.size), "ratio.serialized.gz" = sum(datasets$R.serialize.size.gz) / sum(datasets$object.size), "ratio.rprotobuf.gz" = sum(datasets$RProtoBuf.serialize.size.gz) / sum(datasets$object.size), "savings.serialized" = 1-(sum(datasets$R.serialize.size) / sum(datasets$object.size)), "savings.rprotobuf" = 1-(sum(datasets$RProtoBuf.serialize.size) / sum(datasets$object.size)), "savings.serialized.gz" = 1-(sum(datasets$R.serialize.size.gz) / sum(datasets$object.size)), "savings.rprotobuf.gz" = 1-(sum(datasets$RProtoBuf.serialize.size.gz) / sum(datasets$object.size)), check.names=FALSE) clean.df<-rbind(clean.df, all.df) @ Figure~\ref{fig:compression} shows the space savings $\left(1 - \frac{\textrm{Compressed Size}}{\textrm{Uncompressed Size}}\right)$ for each of the data sets using each of these four methods. The associated table shows the exact data sizes for some outliers and the aggregate of all 104 data sets. Note that Protocol Buffer serialization results in slightly smaller byte streams compared to native \proglang{R} serialization in most cases (red dots), but this difference disappears if the results are compressed with gzip (blue triangles). % Sizes are comparable but Protocol Buffers provide simple getters and % setters in multiple languages instead of requiring other programs to % parse the \proglang{R} serialization % format. % \citep{serialization}. The \code{crimtab} dataset of anthropometry measurements of British prisoners \citep{garson1900metric} and the \code{airquality} dataset of air quality measurements in New York show the greatest difference in the space savings when using Protocol Buffers compared to \proglang{R} native serialization. The \code{crimtab} dataset is a 42 $\times$ 22 table of integers, most equal to 0, and the \code{airquality} dataset is a data frame of 154 observations of 1 numeric and 5 integer variables. In both data sets, the large number of small integer values can be very efficiently encoded by the \emph{Varint} integer encoding scheme used by Protocol Buffers which use a variable number of bytes for each value. The other extreme is represented by the \code{faithful} dataset of waiting time and eruptions of the Old Faithful geyser in Yellowstone National Park, Wyoming, USA \citep{azzalini1990look}. This dataset is a data frame with 272 observations of 2 numeric variables. The \proglang{R} native serialization of repeated numeric values is more space-efficient, resulting in a slightly smaller object size compared to the serialized Protocol Buffer equivalent. This evaluation shows that the \code{rexp.proto} universal \proglang{R} object schema included in \pkg{RProtoBuf} does not in general provide any significant saving in file size compared to the normal serialization mechanism in \proglang{R}. % redundant: which is seen as equally compact. The benefits of \pkg{RProtoBuf} accrue more naturally in applications where multiple programming languages are involved, or when a more concise application-specific schema has been defined. The example in the next section satisfies both of these conditions. \begin{figure}[t!] \begin{center} <>= old.mar<-par("mar") new.mar<-old.mar new.mar[3]<-0 new.mar[4]<-0 my.cex<-1.3 par("mar"=new.mar) plot(clean.df$savings.serialized, clean.df$savings.rprotobuf, pch=1, col="red", las=1, xlab="Serialization Space Savings", ylab="Protocol Buffer Space Savings", xlim=c(0,1),ylim=c(0,1),cex.lab=my.cex, cex.axis=my.cex) points(clean.df$savings.serialized.gz, clean.df$savings.rprotobuf.gz,pch=2, col="blue") # grey dotted diagonal abline(a=0,b=1, col="grey",lty=2,lwd=3) # find point furthest off the X axis. clean.df$savings.diff <- clean.df$savings.serialized - clean.df$savings.rprotobuf clean.df$savings.diff.gz <- clean.df$savings.serialized.gz - clean.df$savings.rprotobuf.gz # The one to label. tmp.df <- clean.df[which(clean.df$savings.diff == min(clean.df$savings.diff)),] # This minimum means most to the left of our line, so pos=2 is label to the left text(tmp.df$savings.serialized, tmp.df$savings.rprotobuf, labels=tmp.df$dataset, pos=2, cex=my.cex) # Some gziped version # text(tmp.df$savings.serialized.gz, tmp.df$savings.rprotobuf.gz, labels=tmp.df$dataset, pos=2, cex=my.cex) # Second one is also an outlier tmp.df <- clean.df[which(clean.df$savings.diff == sort(clean.df$savings.diff)[2]),] # This minimum means most to the left of our line, so pos=2 is label to the left text(tmp.df$savings.serialized, tmp.df$savings.rprotobuf, labels=tmp.df$dataset, pos=2, cex=my.cex) #text(tmp.df$savings.serialized.gz, tmp.df$savings.rprotobuf.gz, labels=tmp.df$dataset, pos=my.cex) tmp.df <- clean.df[which(clean.df$savings.diff == max(clean.df$savings.diff)),] # This minimum means most to the right of the diagonal, so pos=4 is label to the right # Only show the gziped one. #text(tmp.df$savings.serialized, tmp.df$savings.rprotobuf, labels=tmp.df$dataset, pos=4, cex=my.cex) text(tmp.df$savings.serialized.gz, tmp.df$savings.rprotobuf.gz, labels=tmp.df$dataset, pos=4, cex=my.cex) #outlier.dfs <- clean.df[c(which(clean.df$savings.diff == min(clean.df$savings.diff)), legend("topleft", c("Raw", "Gzip Compressed"), pch=1:2, col=c("red", "blue"), cex=my.cex) #interesting.df <- clean.df[unique(c(which(clean.df$savings.diff == min(clean.df$savings.diff)), # which(clean.df$savings.diff == max(clean.df$savings.diff)), # which(clean.df$savings.diff.gz == max(clean.df$savings.diff.gz)), # which(clean.df$dataset == "TOTAL"))),c("dataset", "object.size", "serialized", "gzipped serialized", "RProtoBuf", "gzipped RProtoBuf", "savings.serialized", "savings.serialized.gz", "savings.rprotobuf", "savings.rprotobuf.gz")] interesting.df <- clean.df[as.character(clean.df[,1]) %in% c("crimtab", "airquality", "faithful", "TOTAL"), c("dataset", "object.size", "serialized", "gzipped serialized", "RProtoBuf", "gzipped RProtoBuf", "savings.serialized", "savings.serialized.gz", "savings.rprotobuf", "savings.rprotobuf.gz")] interesting.df <- interesting.df[c(2,1,3,4),] # Print without .00 in xtable interesting.df$object.size <- as.integer(interesting.df$object.size) par("mar"=old.mar) @ \includegraphics[width=0.45\textwidth]{figures/fig-SER} % latex table generated in R 3.0.2 by xtable 1.7-0 package % Wed Nov 26 15:31:30 2014 % updated to R 3.3.1 on Sun Jul 10 17:29:41 CDT 2016 %\begin{table}[ht] %\begin{center} \begin{tabular}{rlrrrrr} \hline Data set & \code{object.size} & \multicolumn{2}{c}{\proglang{R} serialization} & \multicolumn{2}{c}{\pkg{RProtoBuf} serialization} \\ & & default & gzipped & default & gzipped \\ \hline \code{crimtab} & 7,936 & 4,641 (41.5\%) & 714 (91.0\%) & 1,655 (79.1\%) & 576 (92.7\%)\\ \code{airquality} & 5,496 & 4,551 (17.2\%) & 1,242 (77.4\%) & 2,874 (47.7\%) & 1,294 (76.4\%)\\ \code{faithful} & 5,136 & 4,543 (11.5\%) & 1,339 (73.9\%) & 4,936 \phantom{0}(3.9\%) & 1,776 (65.4\%)\\ \hline All & 609,024 & 463,833 (24\%) & 139,814 (77\%) & 436,746 (28\%) & 142,783 (77\%)\\ \hline \end{tabular} \end{center} \caption{(Top) Relative space savings of Protocol Buffers and native \proglang{R} serialization over the raw object sizes of each of the 104 data sets in the \pkg{datasets} package. Points to the left of the dashed $y=x$ line represent datasets that are more efficiently encoded with Protocol Buffers. (Bottom) Absolute space savings of three outlier datasets and the aggregate performance of all datasets. R version 3.3.1 was used for both the figure and the table. } \label{fig:compression} \end{figure} \section{Application: Distributed data collection with MapReduce} \label{sec:mapreduce} Protocol Buffers are used extensively at Google for almost all RPC protocols, and to store structured information on a variety of persistent storage systems \citep{dean2009designs}. Since the initial release in 2010, hundreds of Google's statisticians and software engineers use the \pkg{RProtoBuf} package on a daily basis to interact with these systems from within \proglang{R}. The current section illustrates the power of Protocol Buffers to collect and manage large structured data in one language before analyzing it in \proglang{R}. Our example uses MapReduce \citep{dean2008mapreduce}, which has emerged in the last decade as a popular design pattern to facilitate parallel processing of big data using distributed computing clusters. Big data sets in fields such as particle physics and information processing are often stored in binned (histogram) form in order to reduce storage requirements \citep{scott2009multivariate}. Because analysis over such large data sets may involve very rare phenomenon or deal with highly skewed data sets or inflexible raw data storage systems, unbiased sampling is often not feasible. In these situations, MapReduce and binning may be combined as a pre-processing step for a wide range of statistical and scientific analyses \citep{blocker2013}. There are two common patterns for generating histograms of large data sets in a single pass with MapReduce. In the first method, each mapper task generates a histogram over a subset of the data that it has been assigned, serializes this histogram and sends it to one or more reducer tasks which merge the intermediate histograms from the mappers. In the second method, illustrated in Figure~\ref{fig:mr-histogram-pattern1}, each mapper rounds a data point to a bucket width and outputs that bucket as a key and '1' as a value. Reducers count how many times each key occurs and outputs a histogram to a data store. \begin{figure}[t!] \begin{center} \includegraphics[width=0.9\textwidth]{figures/histogram-mapreduce-diag1.pdf} \end{center} \caption{Diagram of MapReduce histogram generation pattern.} \label{fig:mr-histogram-pattern1} \end{figure} In both methods, the mapper tasks must choose identical bucket boundaries in advance if we are to construct the histogram in a single pass, even though they are analyzing disjoint parts of the input set that may cover different ranges. All distributed tasks involved in the pre-processing as well as any downstream data analysis tasks must share a schema of the histogram representation to coordinate effectively. The \pkg{HistogramTools} package \citep{histogramtools} enhances \pkg{RProtoBuf} by providing a concise schema for \proglang{R} histogram objects: \begin{example} package HistogramTools; message HistogramState { repeated double breaks = 1; repeated int32 counts = 2; optional string name = 3; } \end{example} This \code{HistogramState} message type is designed to be helpful if some of the Map or Reduce tasks are written in \proglang{R}, or if those components are written in other languages and only the resulting output histograms need to be manipulated in \proglang{R}. \subsection[A simple single-machine example for Python to R serialization]{A simple single-machine example for \proglang{Python} to \proglang{R} serialization} To create \code{HistogramState} messages in \proglang{Python} for later consumption by \proglang{R}, we first compile the \code{histogram.proto} descriptor into a python module using the \code{protoc} compiler: \begin{verbatim} protoc histogram.proto --python_out=. \end{verbatim} This generates a Python module called \code{histogram\_pb2.py}, containing both the descriptor information as well as methods to read and manipulate the histogram message data. The following simple Python script uses this generated module to create a histogram (to which breakpoints and binned data are added), and writes out the Protocol Buffer representation to a file: \begin{Code} from histogram_pb2 import HistogramState; hist = HistogramState() hist.counts.extend([2, 6, 2, 4, 6]) hist.breaks.extend(range(6)) hist.name="Example Histogram Created in Python" outfile = open("/tmp/hist.pb", "wb") outfile.write(hist.SerializeToString()) outfile.close() \end{Code} The Protocol Buffer created from this \proglang{Python} script can then be read into \proglang{R} and converted to a native \proglang{R} histogram object for plotting. The code below first attaches the \pkg{HistogramTools} package which imports \pkg{RProtoBuf}. Then reads all of the \code{.proto} descriptor definitions provided by \pkg{HistogramTools} and adds them to the environment as described in Section~\ref{sec:rprotobuf-basic}. Next the serialized Protocol Buffer is parsed using the \code{HistogramTools.HistogramState} schema. Finally the Protocol Buffer representation of the histogram is converted to a native \proglang{R} histogram object with \code{as.histogram} and passes the result to \code{plot} (see Figure~\ref{figure}). \lstdefinelanguage{jss} {sensitive=false, morecomment=[l]{R>}} \lstset{language=jss, basicstyle=\ttfamily, numbers=left, numberstyle=\tiny, stepnumber=2, numbersep=5pt, columns=fullflexible, keepspaces=true, showstringspaces=false, commentstyle=\textsl} %\begin{Code} \begin{lstlisting} R> library("HistogramTools") R> readProtoFiles(package="HistogramTools") R> hist <- HistogramTools.HistogramState$read("/tmp/hist.pb") R> hist [1] "message of type 'HistogramTools.HistogramState' with 3 fields set" R> plot(as.histogram(hist), main="") \end{lstlisting} %\end{Code} %% DEdd 2016-07-10 Taking a shortcut here an showing a prepared %% HistogramTools chart to not depend on HistogramTools %% on Travis CI etc \begin{center} <>= require(HistogramTools) readProtoFiles(package="HistogramTools") hist <- HistogramTools.HistogramState$read("proto/hist.pb") plot(as.histogram(hist), main="") @ \includegraphics[width=0.45\textwidth]{figures/HistogramTools} \end{center} This simple example uses a constant histogram generated in \proglang{Python} to illustrate the serialization concepts without requiring the reader to be familiar with the interface of any particular MapReduce implementation. In practice, using Protocol Buffers to pass histograms between another programming language and \proglang{R} would provide a much greater benefit in a distributed context. For example, a first-class data type to represent histograms would prevent individual histograms from being split up and would allow the use of combiners on Map workers to process large data sets more efficiently than simply passing around lists of counts and buckets. One of the authors has used this design pattern with \proglang{C++} MapReduces over very large data sets to write out histogram protocol buffers for several large-scale studies of distributed storage systems \citep{sciencecloud,janus}. \section{Application: Data interchange in web services} \label{sec:opencpu} The previous section described an application where data from a program written in another language was saved to persistent storage and then read into \proglang{R} for further analysis. This section describes another common use case where Protocol Buffers are used as the interchange format for client-server communication. Network protocols such as HTTP provide mechanisms for client-server communication, i.e., how to initiate requests, authenticate, send messages, etc. However, network protocols generally do not regulate the \emph{content} of messages: they allow transfer of any media type, such as web pages, static files or multimedia content. When designing systems where various components require exchange of specific data structures, we need something on top of the network protocol that prescribes how these structures are to be represented in messages (buffers) on the network. Protocol Buffers solve this problem by providing a cross-platform method for serializing arbitrary structures into well defined messages, which can then be exchanged using any protocol. \subsection[Interacting with R through HTTPS and Protocol Buffers]{Interacting with \proglang{R} through HTTPS and Protocol Buffers} One example of a system that supports Protocol Buffers to interact with \proglang{R} is OpenCPU \citep{opencpu}. OpenCPU is a framework for embedded statistical computation and reproducible research based on \proglang{R} and \LaTeX. It exposes a HTTP(S) API to access and manipulate \proglang{R} objects and execute remote \proglang{R} function calls. Clients do not need to understand or generate any \proglang{R} code: HTTP requests are automatically mapped to function calls, and arguments/return values can be posted/retrieved using several data interchange formats, such as Protocol Buffers. OpenCPU uses the \code{rexp.proto} descriptor and the \code{serialize\_pb} and \code{unserialize\_pb} functions described in Section~\ref{sec:evaluation} to convert between \proglang{R} objects and Protocol Buffer messages. \subsection[HTTP GET: Retrieving an R object]{HTTP GET: Retrieving an \proglang{R} object} The \code{HTTP GET} method is used to read a resource from OpenCPU. For example, to access the data set \code{Animals} from the package \code{MASS}, a client performs the following HTTP request: \begin{verbatim} GET https://demo.ocpu.io/MASS/data/Animals/pb \end{verbatim} The postfix \code{/pb} in the URL tells the server to send this object in the form of a Protocol Buffer message. % Alternative formats include \code{/json}, \code{/csv}, \code{/rds} and others. If the request is successful, OpenCPU returns the serialized object with HTTP status code 200 and HTTP response header \code{Content-Type: application/x-protobuf}. The latter is the conventional MIME type that formally notifies the client to interpret the response as a Protocol Buffer. Because both HTTP and Protocol Buffers have libraries available for many languages, clients can be implemented in just a few lines of code. Below is example code for both \proglang{R} and Python that retrieves an \proglang{R} data set encoded as a Protocol Buffer message from OpenCPU. In \proglang{R}, we use the HTTP client from the \code{httr} package \citep{httr}. In this example we download a data set which is part of the base \proglang{R} distribution, so we can verify that the object was transferred without loss of information. <>= library("RProtoBuf") library("httr") req <- GET('https://demo.ocpu.io/MASS/data/Animals/pb') output <- unserialize_pb(req$content) identical(output, MASS::Animals) @ Similarly, to retrieve the same data set in a \proglang{Python} client, we first compile the \code{rexp.proto} descriptor into a python module using the \code{protoc} compiler: \begin{verbatim} protoc rexp.proto --python_out=. \end{verbatim} This generates \proglang{Python} module called \code{rexp\_pb2.py}, containing both the descriptor information as well as methods to read and manipulate the \proglang{R} object message. We use the HTTP client from the \code{urllib2} module in our example to retrieve the encoded Protocol Buffer from the remote server then parse and print it from \proglang{Python}. \begin{verbatim} import urllib2 from rexp_pb2 import REXP req = urllib2.Request('https://demo.ocpu.io/MASS/data/Animals/pb') res = urllib2.urlopen(req) msg = REXP() msg.ParseFromString(res.read()) print(msg) \end{verbatim} The \code{msg} object contains all data from the \code{Animals} data set. From here we can easily extract the desired fields for further use in \proglang{Python}. \subsection[HTTP POST: Calling an R function]{HTTP POST: Calling an \proglang{R} function} The previous example used a simple \code{HTTP GET} method to retrieve an \proglang{R} object from a remote service (\pkg{OpenCPU}) encoded as a Protocol Buffer. In many cases simple \code{HTTP GET} methods are insufficient, and a more complete RPC system may need to create compact Protocol Buffers for each request to send to the remote server in addition to parsing the response Protocol Buffers. The \pkg{OpenCPU} framework allows us to do arbitrary \proglang{R} function calls from within any programming language by encoding the arguments in the request Protocol Buffer. The following example \proglang{R} client code performs the remote function call \code{stats::rnorm(n = 42, mean = 100)}. The function arguments (in this case \code{n} and \code{mean}) as well as the return value (a vector with 42 random numbers) are transferred using Protocol Buffer messages. RPC in \pkg{OpenCPU} works like the \code{do.call} function in \proglang{R}, hence all arguments are contained within a list. <>= library("httr") library("RProtoBuf") args <- list(n=42, mean=100) payload <- serialize_pb(args, NULL) req <- POST ( url = "https://demo.ocpu.io/stats/R/rnorm/pb", body = payload, add_headers ( "Content-Type" = "application/x-protobuf" ) ) output <- unserialize_pb(req$content) print(output) @ The \pkg{OpenCPU} server basically performs the following steps to process the above RPC request: <>= fnargs <- unserialize_pb(inputmsg) val <- do.call(stats::rnorm, fnargs) outputmsg <- serialize_pb(val) @ \section{Summary} \label{sec:summary} Over the past decade, many formats for interoperable data exchange have become available, each with its unique features, strengths and weaknesses. Text based formats such as CSV and JSON are easy to use, and will likely remain popular among statisticians for many years to come. However, in the context of increasingly complex analysis stacks and applications involving distributed computing as well as mixed language analysis pipelines, choosing a more sophisticated data interchange format may reap considerable benefits. %Protocol Buffers is itself not a protocol. %Forward-compatibility is one of the features. No need to re-iterate those The Protocol Buffers standard and library offer a unique combination of features, performance, and maturity, that seems particularly well suited for data-driven applications and numerical computing. The \pkg{RProtoBuf} package builds on the Protocol Buffers \proglang{C++} library, and extends the \proglang{R} system with the ability to create, read, write, parse, and manipulate Protocol Buffer messages. \pkg{RProtoBuf} has been used extensively inside Google for the past five years by statisticians, analysts, and software engineers. At the time of this writing there are over 300 active users of \pkg{RProtoBuf} using it to read data from and otherwise interact with distributed systems written in \proglang{C++}, \proglang{Java}, \proglang{Python}, and other languages. We hope that making Protocol Buffers available to the \proglang{R} community will contribute to better software integration and allow for building even more advanced applications and analysis pipelines with \proglang{R}. \section*{Acknowledgments} The first versions of \pkg{RProtoBuf} were written during 2009--2010. Very significant contributions, both in code and design, were made by Romain Fran\c{c}ois whose continued influence on design and code is greatly appreciated. Several features of the package reflect the design of the \pkg{rJava} package by Simon Urbanek \citep{rjava}. The user-defined table mechanism, implemented by Duncan Temple Lang for the purpose of the \pkg{RObjectTables} package, allows for the dynamic symbol lookup. Kenton Varda was generous with his time in reviewing code and explaining obscure Protocol Buffer semantics. Karl Millar and Tim Hesterberg were very helpful in reviewing code and offering suggestions. Saptarshi Guha's work on \pkg{RHIPE} and implementation of a universal message type for \proglang{R} language objects allowed us to add the \code{serialize_pb} and \code{unserialize_pb} methods for turning arbitrary \proglang{R} objects into Protocol Buffers without a specialized pre-defined schema. Feedback from two anonymous referees greatly improved both the presentation of this paper and the package contents. \bibliography{RProtoBuf-paper} \begin{appendix} \section[The rexp.proto schema descriptor]{The \code{rexp.proto} schema descriptor} \label{rexp.proto} Below a print of the \code{rexp.proto} schema (originally designed by \citealt{rhipe}) that is included with the \pkg{RProtoBuf} package and used by \code{serialize\_pb} and \code{unserialize\_pb}. \begin{verbatim} package rexp; message REXP { enum RClass { STRING = 0; RAW = 1; REAL = 2; COMPLEX = 3; INTEGER = 4; LIST = 5; LOGICAL = 6; NULLTYPE = 7; LANGUAGE = 8; ENVIRONMENT = 9; FUNCTION = 10; } enum RBOOLEAN { F=0; T=1; NA=2; } required RClass rclass = 1; repeated double realValue = 2 [packed=true]; repeated sint32 intValue = 3 [packed=true]; repeated RBOOLEAN booleanValue = 4; repeated STRING stringValue = 5; optional bytes rawValue = 6; repeated CMPLX complexValue = 7; repeated REXP rexpValue = 8; repeated string attrName = 11; repeated REXP attrValue = 12; optional bytes languageValue = 13; optional bytes environmentValue = 14; optional bytes functionValue = 15; } message STRING { optional string strval = 1; optional bool isNA = 2 [default=false]; } message CMPLX { optional double real = 1 [default=0]; required double imag = 2; } \end{verbatim} \end{appendix} \end{document} RProtoBuf/vignettes/RProtoBuf-paper.bib0000644000176200001440000002516413005133352017614 0ustar liggesusers@Misc{apache:avro, author = {{Apache Software Foundation}}, title = {Apache Avro}, url = {http://avro.apache.org/}, note = {Data Serialization System, Version 1.8.1}, year = 2016, } @Misc{apache:thrift, author = {{Apache Software Foundation}}, title = {Apache Thrift}, url = {http://thrift.apache.org/}, note = {Software Framework for Scalable Cross-Language Services, Version 0.9.3}, year = 2015, } @Manual{cran:rserve, title = {\pkg{Rserve}: Binary \proglang{R} Server}, author = {Simon Urbanek}, year = 2013, note = {\proglang{R} package version 1.7-3}, url = {https://CRAN.R-Project.org/package=Rserve}, } @Manual{rjsonio, title = {\pkg{RJSONIO}: Serialize \proglang{R} Objects to JSON, \proglang{JavaScript} Object Notation}, author = {Duncan {Temple Lang}}, year = 2014, note = {\proglang{R} package version 1.3-0}, url = {https://CRAN.R-project.org/package=RJSONIO}, } @Manual{robjecttables, title = {User-Defined Tables in the \proglang{R} Search Path}, author = {Duncan {Temple Lang}}, year = 2012, url = {http://www.omegahat.net/RObjectTables/RObjectTables.pdf}, } @InProceedings{sumaray:2012:cds:2184751.2184810, author = {Audie Sumaray and S. Makki}, title = {A Comparison of Data Serialization Formats for Optimal Efficiency on a Mobile Platform}, booktitle = {Proceedings of the 6th International Conference on Ubiquitous Information Management and Communication}, series = {ICUIMC '12}, year = 2012, location = {Kuala Lumpur, Malaysia}, pages = {48:1--48:6}, articleno = 48, numpages = 6, doi = {10.1145/2184751.2184810}, publisher = {ACM}, address = {New York}, } @InProceedings{urbanek:2003:rserve, author = {Simon Urbanek}, title = {\pkg{Rserve}: A Fast Way to Provide {\proglang{R}} Functionality to Applications}, booktitle = {Proceedings of the 3rd International Workshop on Distributed Statistical Computing, Vienna, Austria}, editor = {Kurt Hornik and Friedrich Leisch and Achim Zeileis}, year = 2003, url = {https://www.R-project.org/conferences/DSC-2003/Proceedings/}, note = {{ISSN 1609-395X}}, } @Article{wegiel:2010:ctt:1932682.1869479, author = {Michal Wegiel and Chandra Krintz}, title = {Cross-Language, Type-Safe, and Transparent Object Sharing for Co-Located Managed Runtimes}, journal = {SIGPLAN Notices}, issue_date = {October 2010}, volume = 45, number = 10, year = 2010, pages = {223--240}, doi = {10.1145/1932682.1869479}, publisher = {ACM}, address = {New York}, } @Article{azzalini1990look, title = {A Look at Some Data on the Old Faithful Geyser}, author = {A Azzalini and A W Bowman}, journal = {Applied Statistics}, volume = 39, number = 3, pages = {357--365}, year = 1990, doi = {10.2307/2347385}, } @Manual{bit64, title = {\pkg{bit64}: A \proglang{S}3 Class for Vectors of 64bit Integers}, author = {Jens Oehlschl{\"a}gel}, year = 2015, note = {\proglang{R} package version 0.9-5}, url = {https://CRAN.R-project.org/package=bit64}, } @Article{blocker2013, author = {Alexander Blocker and Xiao-Li Meng}, doi = {10.3150/13-bejsp16}, journal = {Bernoulli}, number = 4, pages = {1176--1211}, title = {The Potential and Perils of Preprocessing: Building New Foundations}, volume = 19, year = 2013, } @Manual{clinec++, title = {\proglang{C++} FAQ}, author = {Marshall Cline}, url = {http://www.parashift.com/c++-faq-lite/}, year = 2013, } @Article{dean2008mapreduce, title = {MapReduce: Simplified Data Processing on Large Clusters}, author = {Jeffrey Dean and Sanjay Ghemawat}, journal = {Communications of the ACM}, volume = 51, number = 1, pages = {107--113}, year = 2008, publisher = {ACM}, doi = {10.1145/1327452.1327492}, } @Article{dean2009designs, title = {Designs, Lessons and Advice from Building Large Distributed Systems}, author = {Jeff Dean}, journal = {Keynote from LADIS}, year = 2009, } @Article{eddelbuettel2011rcpp, title = {\pkg{Rcpp}: Seamless \proglang{R} and \proglang{C++} Integration}, author = {Dirk Eddelbuettel and Romain Fran{\c{c}}ois}, journal = {Journal of Statistical Software}, volume = 40, number = 8, pages = {1--18}, year = 2011, doi = {10.18637/jss.v040.i08}, } @Manual{eddelbuettel2013exposing, title = {Exposing \proglang{C++} Functions and Classes with \pkg{Rcpp} Modules}, author = {Dirk Eddelbuettel and Romain Fran{\c{c}}ois}, year = 2016, note = {Vignette \verb|"Rcpp-modules"| included in \proglang{R} package \pkg{Rcpp}}, url = {https://CRAN.R-project.org/package=Rcpp}, } @Book{eddelbuettel2013seamless, title = {Seamless \proglang{R} and \proglang{C++} Integration with \pkg{Rcpp}}, author = {Dirk Eddelbuettel}, year = 2013, publisher = {Springer-Verlag}, } @Article{garson1900metric, title = {The Metric System of Identification of Criminals, as Used in Great Britain and Ireland}, author = {John Garson}, journal = {Journal of the Anthropological Institute of Great Britain and Ireland}, pages = {161--198}, volume = 30, year = 1900, doi = {10.2307/2842627}, } @Manual{histogramtools, title = {\pkg{HistogramTools}: Utility Functions for \proglang{R} Histograms}, author = {Murray Stokely}, year = 2015, note = {\proglang{R} package version 0.3.2}, url = {https://CRAN.R-project.org/package=HistogramTools}, } @Manual{httr, title = {\pkg{httr}: Tools for Working with URLs and HTTP}, author = {Hadley Wickham}, year = 2016, note = {\proglang{R} package version 1.2.1}, url = {https://CRAN.R-project.org/package=httr}, } @Manual{int64, title = {\pkg{int64}: 64 Bit Integer Types}, author = {Romain Fran{\c{c}}ois}, year = 2011, note = {Archived \proglang{R} package version 1.1.2}, url = {https://CRAN.R-project.org/src/contrib/Archive/int64/}, } @InProceedings{janus, title = {Janus: Optimal Flash Provisioning for Cloud Storage Workloads}, author = {Christoph Albrecht and Arif Merchant and Murray Stokely and Muhammad Waliji and Francois Labelle and Nathan Coehlo and Xudong Shi and Eric Schrock}, year = 2013, url = {https://www.usenix.org/system/files/conference/atc13/atc13-albrecht.pdf}, booktitle = {Proceedings of the USENIX Annual Technical Conference}, pages = {91--102}, address = {Berkeley}, } @Unpublished{jsonlite, title = {The \pkg{jsonlite} Package: A Practical and Consistent Mapping Between JSON Data and \proglang{R} Objects}, note = {{arXiv}:1403.2805 [stat.CO]}, author = {Jeroen Ooms}, year = 2014, pages = {1--29}, url = {http://arxiv.org/abs/1403.2805}, } @Book{nolan2013xml, title = {XML and Web Technologies for Data Sciences with \proglang{R}}, author = {Deborah Nolan and Duncan {Temple Lang}}, year = 2013, publisher = {Springer-Verlag}, address = {New York} } @Unpublished{opencpu, title = {The \pkg{OpenCPU} System: Towards a Universal Interface for Scientific Computing through Separation of Concerns}, author = {Jeroen Ooms}, year = 2014, note = {{arXiv}:1406.4806 [stat.CO]}, url = {http://arxiv.org/abs/1406.4806}, } @Manual{protobuf, title = {Protocol Buffers: Developer Guide}, author = {{Google, Inc.}}, year = 2012, url = {http://code.google.com/apis/protocolbuffers/docs/overview.html}, } @Manual{r, title = {\proglang{R}: A Language and Environment for Statistical Computing}, author = {{\proglang{R} Core Team}}, organization = {\proglang{R} Foundation for Statistical Computing}, address = {Vienna, Austria}, year = 2016, url = {https://www.R-project.org/}, } @Manual{rhipe, title = {\pkg{RHIPE}: A Distributed Environment for the Analysis of Large and Complex Datasets}, author = {Saptarshi Guha}, year = 2010, url = {http://www.stat.purdue.edu/~sguha/rhipe/}, } @Manual{rjson, title = {\pkg{rjson}: JSON for \proglang{R}}, author = {Alex Couture-Beil}, year = 2014, note = {\proglang{R} package version 0.2.15}, url = {https://CRAN.R-project.org/package=rjson}, } @InProceedings{sciencecloud, title = {Projecting Disk Usage Based on Historical Trends in a Cloud Environment}, author = {Murray Stokely and Amaan Mehrabian and Christoph Albrecht and Francois Labelle and Arif Merchant}, year = 2012, booktitle = {ScienceCloud 2012 Proceedings of the 3rd International Workshop on Scientific Cloud Computing}, pages = {63--70}, } @Book{scott2009multivariate, title = {Multivariate Density Estimation: Theory, Practice, and Visualization}, author = {David Scott}, volume = 383, year = 2009, publisher = {John Wiley \& Sons}, doi = {10.1002/9781118575574}, } @Misc{serialization, author = {Luke Tierney}, title = {A New Serialization Mechanism for \proglang{R}}, url = {http://www.cs.uiowa.edu/~luke/R/serialize/serialize.ps}, year = 2003, } @Misc{shafranovich2005common, title = {Common Format and Mime Type for Comma-Separated Values (CSV) Files}, author = {Yakov Shafranovich}, year = 2005, url = {http://tools.ietf.org/html/rfc4180}, } @Book{MASS, title = {Modern Applied Statistics with \proglang{S}}, author = {W. N. Venables and B. D. Ripley}, publisher = {Springer-Verlag}, edition = {4th}, address = {New York}, year = 2002, } @Unpublished{julia, title = {\proglang{Julia}: A Fast Dynamic Language for Technical Computing}, author = {Jeff Bezanson and Stefan Karpinski and Viral B. Shah and Alan Edelman}, year = 2012, url = {http://arxiv.org/abs/1209.5145}, note = {{arXiv}:1209.5145 [cs.PL]}, } @Manual{python, author = {Van Rossum, Guido and {others}}, title = {\proglang{Python} Programming Language}, url = {http://www.python.org}, year = {2011} } @Manual{rjava, title = {\pkg{rJava}: Low-Level \proglang{R} to \proglang{Java} Interface}, author = {Simon Urbanek}, year = {2016}, note = {\proglang{R} package version 0.9-8}, url = {https://CRAN.R-project.org/package=rJava}, } RProtoBuf/vignettes/RProtoBuf-unitTests.Rnw0000644000176200001440000000420413005133352020511 0ustar liggesusers\documentclass[10pt]{article} %\VignetteIndexEntry{RProtoBuf-unitTests} %\VignetteKeywords{RProtoBuf, Protocol Buffers, package} %\VignetteDepends{RProtoBuf} \usepackage{vmargin} \setmargrb{0.75in}{0.75in}{0.75in}{0.75in} <>= require(RProtoBuf) prettyVersion <- packageDescription("RProtoBuf")$Version prettyDate <- format(Sys.Date(), "%B %e, %Y") library(RUnit) @ \usepackage{microtype} %% cf http://www.khirevich.com/latex/microtype/ \usepackage[T1]{fontenc} %% cf http://www.khirevich.com/latex/font/ \usepackage[bitstream-charter]{mathdesign} %% cf http://www.khirevich.com/latex/font/ \usepackage[colorlinks]{hyperref} \author{Romain Fran\c{c}ois \and Dirk Eddelbuettel \and Murray Stokely} \title{RProtoBuf : Unit testing results} \date{RProtoBuf version \Sexpr{prettyVersion} as of \Sexpr{prettyDate}} \begin{document} \maketitle \section*{Test Execution} <>= pkg <- "RProtoBuf" if (file.exists("unitTests-results")) unlink("unitTests-results", recursive = TRUE) dir.create("unitTests-results") pathRcppTests <<- system.file("unitTests", package = pkg) path <- system.file("unitTests", package=pkg) testSuite <- defineTestSuite(name=paste(pkg, "unit testing"), dirs=path) tests <- runTestSuite(testSuite) err <- getErrors(tests) if (err$nFail > 0) cat(sprintf("unit test problems: %d failures", err$nFail)) if (err$nErr > 0) cat(sprintf("unit test problems: %d errors", err$nErr)) printHTMLProtocol(tests, fileName=sprintf("unitTests-results/%s-unitTests.html", pkg)) printTextProtocol(tests, fileName=sprintf("unitTests-results/%s-unitTests.txt" , pkg)) #if (file.exists("/tmp")) { # invisible(sapply(c("txt", "html"), function(ext) { # fname <- sprintf("unitTests-results/%s-unitTests.%s", pkg, ext) # file.copy(fname, "/tmp", overwrite=TRUE) # })) #} @ \section*{Test Results} \begin{verbatim} <>= results <- sprintf("unitTests-results/%s-unitTests.txt", pkg) if (file.exists(results)) { writeLines(readLines(results)) } else{ writeLines("Unit test results not available") } @ \end{verbatim} \end{document} RProtoBuf/vignettes/RProtoBuf-quickref.Rmd0000644000176200001440000000773113164233540020312 0ustar liggesusers--- title: \pkg{RProtoBuf} Quick Reference Guide # Use letters for affiliations author: - name: Dirk Eddelbuettel affiliation: a - name: Romain François affiliation: b - name: Murray Stokely affiliation: c address: - code: a address: \url{http://dirk.eddelbuettel.com} - code: b address: \url{https://romain.rbind.io/} - code: c address: \url{https://stokely.org} # For footer text lead_author_surname: Eddelbuettel, François and Stokely # Place DOI URL or CRAN Package URL here doi: "https://cran.r-project.org/package=RProtoBuf" # Customize footer, eg by referencing the vignette footer_contents: "RProtoBuf Vignette" # Produce a pinp document output: pinp::pinp header-includes: > \newcommand{\proglang}[1]{\textsf{#1}} \newcommand{\pkg}[1]{\textbf{#1}} \newcommand{\faq}[1]{FAQ~\ref{#1}} \newcommand{\rdoc}[2]{\href{http://www.rdocumentation.org/packages/#1/functions/#2}{\code{#2}}} \newcommand{\sugar}{\textsl{Rcpp sugar}~} vignette: > %\VignetteIndexEntry{RProtoBuf-quickref} %\VignetteKeywords{RProtoBuf, Protocol Buffers, package} %\VignetteDepends{RProtoBuf} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r init, echo=FALSE} library("RProtoBuf") options("width"=48) ``` ## Example proto file ```{r readab, echo=FALSE, comment=""} ab.proto <- system.file("proto", "addressbook.proto", package = "RProtoBuf") writeLines(readLines(ab.proto)) ``` ## Read proto description files ```{r readproto, eval=FALSE} readProtoFiles("somefile.proto") readProtoFiles(dir = somedir) readProtoFiles(package = AnRPackage) ``` ## Create a message ```{r createmsg} message <- new(tutorial.Person, id = 0, name = "Romain Francois", email = "francoisromain@free.fr") ``` ## Serialize a message to a file or binary connection ```{r serialize} # to a file tf1 <- tempfile() message$serialize(tf1) # to a binary connection tf2 <- tempfile() con <- file(tf2, open = "wb") message$serialize(con) close(con) # retrieve the payload message$serialize(NULL) ``` ## Read a message from a file or binary connection} ```{r readbin, eval=FALSE} # from a file tutorial.Person$read(tf1) # from a connection con <- file(tf2, open = "rb") tutorial.Person$read(con) close(con) ``` ## Get/Set fields ```{r getset} email <- message$email message$id <- 2 message[["name"]] <- "Romain" id <- message[[2]] # tag number for 'id' ``` ## Message methods \begin{center} \begin{small} \begin{tabular}{cp{2.2in}} \hline \texttt{has} & Indicates if a message has a given field. \\ \texttt{clone} & Creates a clone of the message \\ \texttt{isInitialized} & Indicates if a message has all its required fields set\\ \texttt{serialize} & serialize a message to a file or a binary connection or retrieve the message payload as a raw vector\\ \texttt{clear} & Clear one or several fields of a message, or the entire message\\ \texttt{size} & The number of elements in a message field\\ \texttt{bytesize} & The number of bytes the message would take once serialized\\ \hline \texttt{swap} & swap elements of a repeated field of a message\\ \texttt{set} & set elements of a repeated field\\ \texttt{fetch} & fetch elements of a repeated field\\ \texttt{add} & add elements to a repeated field \\ \hline \texttt{str} & the R structure of the message\\ \texttt{as.character} & character representation of a message\\ \texttt{toString} & character representation of a message (same as \texttt{as.character}) \\ \texttt{update} & updates several fields of a message at once\\ \texttt{descriptor} & get the descriptor of the message type of this message\\ \hline \end{tabular} \end{small} \end{center} ## More info \begin{center} \begin{small} \begin{tabular}{cp{2.2in}} Full Vignette & \verb|vignette("RProtoBuf-intro")| \\ JSS Paper & \verb|vignette("RProtoBuf-paper")| \\ Protocol Buffers & \url{https://developers.google.com/protocol-buffers/} \\ RProtoBuf & \url{https://github.com/eddelbuettel/rprotobuf}\\ \end{tabular} \end{small} \end{center} RProtoBuf/vignettes/RProtoBuf-intro.Rmd0000644000176200001440000021244313164231540017630 0ustar liggesusers--- title: | | \pkg{RProtoBuf}: An R API for Protocol Buffers # Use letters for affiliations author: - name: Dirk Eddelbuettel affiliation: a - name: Romain François affiliation: b - name: Murray Stokely affiliation: c address: - code: a address: \url{http://dirk.eddelbuettel.com} - code: b address: \url{https://romain.rbind.io/} - code: c address: \url{https://stokely.org} # For footer text lead_author_surname: Eddelbuettel, François and Stokely # Place DOI URL or CRAN Package URL here doi: "https://cran.r-project.org/package=RProtoBuf" # Customize footer, eg by referencing the vignette footer_contents: "RProtoBuf Vignette" # Abstract abstract: | \textsl{Protocol Buffers} is a software project by Google that is used extensively internally and also released under an Open Source license. It provides a way of encoding structured data in an efficient yet extensible format. Google formally supports APIs for C++, Java and Python. This vignette describes version the \texttt{RProtoBuf} package which brings support for Protocol Buffer messages to R. # Font size of the document, values of 9pt (default), 10pt, 11pt and 12pt fontsize: 10pt # Optional: Force one-column layout, default is two-column one_column: true # Optional: Enable section numbering, default is unnumbered numbersections: true # Optional: Specify the depth of section number, default is 5 secnumdepth: 5 # Produce a pinp document output: pinp::pinp # Optional extra LaTeX definitions header-includes: > \newcommand{\proglang}[1]{\textsf{#1}} \newcommand{\pkg}[1]{\textbf{#1}} \newcommand{\faq}[1]{FAQ~\ref{#1}} \newcommand{\rdoc}[2]{\href{http://www.rdocumentation.org/packages/#1/functions/#2}{\code{#2}}} \newcommand{\sugar}{\textsl{Rcpp sugar}~} # Declarations for R vignette indices vignette: > %\VignetteIndexEntry{RProtoBuf-intro} %\VignetteKeywords{RProtoBuf, Protocol Buffers, package} %\VignetteDepends{RProtoBuf} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r init, echo=FALSE} library("RProtoBuf") options("width"=90) ``` \tableofcontents # Protocol Buffers Protocol Buffers are a language-neutral, platform-neutral, extensible way of serializing structured data for use in communications protocols, data storage, and more. Protocol Buffers offer key features such as an efficient data interchange format that is both language- and operating system-agnostic yet uses a lightweight and highly performant encoding, object serialization and de-serialization as well data and configuration management. Protocol Buffers are also forward compatible: updates to the \texttt{proto} files do not break programs built against the previous specification. While benchmarks are not available, Google states on the project page that in comparison to XML, Protocol Buffers are at the same time \textsl{simpler}, between three to ten times \textsl{smaller}, between twenty and one hundred times \textsl{faster}, as well as less ambiguous and easier to program. The Protocol Buffers code is released under an open-source (BSD) license. The Protocol Buffer project (\url{http://code.google.com/p/protobuf/}) contains a C++ library and a set of runtime libraries and compilers for C++, Java and Python. With these languages, the workflow follows standard practice of so-called Interface Description Languages (IDL) (c.f. \href{http://en.wikipedia.org/wiki/Interface_description_language}{Wikipedia on IDL}). This consists of compiling a Protocol Buffer description file (ending in \texttt{.proto}) into language specific classes that can be used to create, read, write and manipulate Protocol Buffer messages. In other words, given the 'proto' description file, code is automatically generated for the chosen target language(s). The project page contains a tutorial for each of these officially supported languages: \url{http://code.google.com/apis/protocolbuffers/docs/tutorials.html} Besides the officially supported C++, Java and Python implementations, several projects have been created to support Protocol Buffers for many languages. The list of known languages to support protocol buffers is compiled as part of the project page: \url{http://code.google.com/p/protobuf/wiki/ThirdPartyAddOns} The Protocol Buffer project page contains a comprehensive description of the language: \url{http://code.google.com/apis/protocolbuffers/docs/proto.html} # Basic use: Protocol Buffers and R This section describes how to use the R API to create and manipulate protocol buffer messages in R, and how to read and write the binary \emph{payload} of the messages to files and arbitrary binary R connections. ## Importing proto files dynamically In contrast to the other languages (Java, C++, Python) that are officially supported by Google, the implementation used by the \texttt{RProtoBuf} package does not rely on the \texttt{protoc} compiler (with the exception of the two functions discussed in the previous section). This means that no initial step of statically compiling the proto file into C++ code that is then accessed by R code is necessary. Instead, \texttt{proto} files are parsed and processed \textsl{at runtime} by the protobuf C++ library---which is much more appropriate for a dynamic language. The \texttt{readProtoFiles} function allows importing \texttt{proto} files in several ways. ```{r readproto} args(readProtoFiles) ``` Using the \texttt{file} argument, one can specify one or several file paths that ought to be proto files. ```{r loadprotos, eval=FALSE} pdir <- system.file("proto", package = "RProtoBuf") pfile <- file.path(pdir, "addressbook.proto") readProtoFiles(pfile) ``` With the \texttt{dir} argument, which is ignored if the \texttt{file} is supplied, all files matching the \texttt{.proto} extension will be imported. ```{r readir, eval=FALSE} dir(pdir, pattern = "\\.proto$", full.names = TRUE) readProtoFiles(dir = pdir) ``` Finally, with the \texttt{package} argument (ignored if \texttt{file} or \texttt{dir} is supplied), the function will import all \texttt{.proto} files that are located in the \texttt{proto} sub-directory of the given package. A typical use for this argument is in the \texttt{.onLoad} function of a package. ```{r protofrompackage, eval=FALSE} readProtoFiles( package = "RProtoBuf" ) ``` Once the proto files are imported, all message descriptors are available in the R search path in the \texttt{RProtoBuf:DescriptorPool} special environment. The underlying mechanism used here is described in more detail in section~\ref{sec-lookup}. ```{r lsproto} ls("RProtoBuf:DescriptorPool") ``` ## Creating a message The objects contained in the special environment are descriptors for their associated message types. Descriptors will be discussed in detail in another part of this document, but for the purpose of this section, descriptors are just used with the \texttt{new} function to create messages. ```{r newmsg} p <- new(tutorial.Person, name = "Romain", id = 1) ``` ## Access and modify fields of a message Once the message is created, its fields can be queried and modified using the dollar operator of R, making protocol buffer messages seem like lists. ```{r modmsg} p$name p$id p$email <- "francoisromain@free.fr" ``` However, as opposed to R lists, no partial matching is performed and the name must be given entirely. The \verb|[[| operator can also be used to query and set fields of a message, supplying either their name or their tag number : ```{r modfields} p[["name"]] <- "Romain Francois" p[[ 2 ]] <- 3 p[[ "email" ]] ``` Protocol buffers include a 64-bit integer type, but R lacks native 64-bit integer support. A workaround is available and described in Section~\ref{sec:int64} for working with large integer values. ## Display messages Protocol buffer messages and descriptors implement \texttt{show} methods that provide basic information about the message : ```{r msgdisp} p ``` For additional information, such as for debugging purposes, the \texttt{as.character} method provides a more complete ASCII representation of the contents of a message. ```{r writeaschar} cat(as.character(p)) ``` ## Serializing messages However, the main focus of protocol buffer messages is efficiency. Therefore, messages are transported as a sequence of bytes. The \texttt{serialize} method is implemented for protocol buffer messages to serialize a message into the sequence of bytes (raw vector in R speech) that represents the message. ```{r serial1} serialize( p, NULL ) ``` The same method can also be used to serialize messages to files : ```{r serial2} tf1 <- tempfile() tf1 serialize( p, tf1 ) readBin(tf1, raw(0), 500) ``` Or to arbitrary binary connections: ```{r serial3} tf2 <- tempfile() con <- file(tf2, open = "wb") serialize(p, con) close(con) readBin(tf2, raw(0), 500) ``` \texttt{serialize} can also be used in a more traditional object oriented fashion using the dollar operator : ```{r serial4} # serialize to a file p$serialize(tf1) # serialize to a binary connection con <- file(tf2, open = "wb") p$serialize(con) close(con) ``` ## Parsing messages The \texttt{RProtoBuf} package defines the \texttt{read} function to read messages from files, raw vector (the message payload) and arbitrary binary connections. ```{r parse1} args(read) ``` The binary representation of the message (often called the payload) does not contain information that can be used to dynamically infer the message type, so we have to provide this information to the \texttt{read} function in the form of a descriptor : ```{r parse2} message <- read(tutorial.Person, tf1) cat(as.character(message)) ``` The \texttt{input} argument of \texttt{read} can also be a binary readable R connection, such as a binary file connection: ```{r parse3} con <- file(tf2, open = "rb") message <- read(tutorial.Person, con) close(con) cat(as.character(message)) ``` Finally, the payload of the message can be used : ```{r parse4} # reading the raw vector payload of the message payload <- readBin(tf1, raw(0), 5000) message <- read( tutorial.Person, payload ) ``` \texttt{read} can also be used as a pseudo method of the descriptor object : ```{r parse5} # reading from a file message <- tutorial.Person$read(tf1) # reading from a binary connection con <- file(tf2, open = "rb") message <- tutorial.Person$read(con) close(con) # read from the payload message <- tutorial.Person$read(payload) ``` ## Classes, Methods and Pseudo Methods The \texttt{RProtoBuf} package uses the S4 system to store information about descriptors and messages, but the information stored in the R object is very minimal and mainly consists of an external pointer to a C++ variable that is managed by the \texttt{proto} C++ library. ```{r classes1, eval=FALSE} str(p) ``` Using the S4 system allows the \texttt{RProtoBuf} package to dispatch methods that are not generic in the S3 sense, such as \texttt{new} and \texttt{serialize}. The \texttt{RProtoBuf} package combines the \emph{R typical} dispatch of the form \verb|method( object, arguments)| and the more traditional object oriented notation \verb|object$method(arguments)|. ## Messages Messages are represented in R using the \texttt{Message} S4 class. The class contains the slots \texttt{pointer} and \texttt{type} as described on the Table~\ref{Message-class-table}. \begin{table}[h] \centering \begin{tabular}{|cp{10cm}|} \hline \textbf{slot} & \textbf{description} \\ \hline \texttt{pointer} & external pointer to the \texttt{Message} object of the C++ proto library. Documentation for the \texttt{Message} class is available from the protocol buffer project page: \url{http://code.google.com/apis/protocolbuffers/docs/reference/cpp/google.protobuf.message.html#Message} \\ \hline \texttt{type} & fully qualified path of the message. For example a \texttt{Person} message has its \texttt{type} slot set to \texttt{tutorial.Person} \\ \hline \end{tabular} \caption{\label{Message-class-table}Description of slots for the \texttt{Message} S4 class} \end{table} Although the \texttt{RProtoBuf} package uses the S4 system, the \verb|@| operator is very rarely used. Fields of the message are retrieved or modified using the \verb|$| or \verb|[[| operators as seen on the previous section, and pseudo-methods can also be called using the \verb|$| operator. Table~\ref{Message-methods-table} describes the methods defined for the \texttt{Message} class : \begin{table}[h] \centering \begin{small} \begin{tabular}{|ccp{8cm}|} \hline \textbf{method} & \textbf{section} & \textbf{description} \\ \hline \hline \texttt{has} & \ref{Message-method-has} & Indicates if a message has a given field. \\ \texttt{clone} & \ref{Message-method-clone} & Creates a clone of the message \\ \texttt{isInitialized} & \ref{Message-method-isInitialized} & Indicates if a message has all its required fields set\\ \texttt{serialize} & \ref{Message-method-serialize} & serialize a message to a file or a binary connection or retrieve the message payload as a raw vector\\ \texttt{clear} & \ref{Message-method-clear} & Clear one or several fields of a message, or the entire message\\ \texttt{size} & \ref{Message-method-size} & The number of elements in a message field\\ \texttt{bytesize} & \ref{Message-method-bytesize} & The number of bytes the message would take once serialized\\ \hline \texttt{swap} & \ref{Message-method-swap} & swap elements of a repeated field of a message\\ \texttt{set} & \ref{Message-method-set} & set elements of a repeated field\\ \texttt{fetch} & \ref{Message-method-fetch} & fetch elements of a repeated field\\ \texttt{setExtension} & \ref{Message-method-setExtension} & set an extension of a message\\ \texttt{getExtension} & \ref{Message-method-getExtension} & get the value of an extension of a message\\ \texttt{add} & \ref{Message-method-add} & add elements to a repeated field \\ \hline \texttt{str} & \ref{Message-method-str} & the R structure of the message\\ \texttt{as.character} & \ref{Message-method-ascharacter} & character representation of a message\\ \texttt{toString} & \ref{Message-method-toString} & character representation of a message (same as \texttt{as.character}) \\ \texttt{as.list} & \ref{Message-method-aslist} & converts message to a named R list\\ \texttt{update} & \ref{Message-method-update} & updates several fields of a message at once\\ \texttt{descriptor} & \ref{Message-method-descriptor} & get the descriptor of the message type of this message\\ \texttt{fileDescriptor} & \ref{Message-method-fileDescriptor} & get the file descriptor of this message's descriptor\\ \hline \end{tabular} \end{small} \caption{\label{Message-methods-table}Description of methods for the \texttt{Message} S4 class} \end{table} ### Retrieve fields \label{Message-method-getfield} The \verb|$| and \verb|[[| operators allow extraction of a field data. ```{r retrieve} message <- new(tutorial.Person, name = "foo", email = "foo@bar.com", id = 2, phone = list(new(tutorial.Person.PhoneNumber, number = "+33(0)...", type = "HOME"), new(tutorial.Person.PhoneNumber, number = "+33(0)###", type = "MOBILE") ) ) message$name message$email message[["phone"]] # using the tag number message[[2]] # id ``` Neither \verb|$| nor \verb|[[| support partial matching of names. The \verb|$| is also used to call methods on the message, and the \verb|[[| operator can use the tag number of the field. Table~\ref{table-get-types} details correspondence between the field type and the type of data that is retrieved by \verb|$| and \verb|[[|. \begin{table}[h] \centering \begin{small} \begin{tabular}{|c|p{5cm}p{5cm}|} \hline field type & R type (non repeated) & R type (repeated) \\ \hline \hline double & \texttt{double} vector & \texttt{double} vector \\ float & \texttt{double} vector & \texttt{double} vector \\ \hline uint32 & \texttt{double} vector & \texttt{double} vector \\ fixed32 & \texttt{double} vector & \texttt{double} vector \\ \hline int32 & \texttt{integer} vector & \texttt{integer} vector \\ sint32 & \texttt{integer} vector & \texttt{integer} vector \\ sfixed32 & \texttt{integer} vector & \texttt{integer} vector \\ \hline int64 & \texttt{integer} or \texttt{character} vector \footnotemark & \texttt{integer} or \texttt{character} vector \\ uint64 & \texttt{integer} or \texttt{character} vector & \texttt{integer} or \texttt{character} vector \\ sint64 & \texttt{integer} or \texttt{character} vector & \texttt{integer} or \texttt{character} vector \\ fixed64 & \texttt{integer} or \texttt{character} vector & \texttt{integer} or \texttt{character} vector \\ sfixed64 & \texttt{integer} or \texttt{character} vector & \texttt{integer} or \texttt{character} vector \\ \hline bool & \texttt{logical} vector & \texttt{logical} vector \\ \hline string & \texttt{character} vector & \texttt{character} vector \\ bytes & \texttt{character} vector & \texttt{character} vector \\ \hline enum & \texttt{integer} vector & \texttt{integer} vector \\ \hline message & \texttt{S4} object of class \texttt{Message} & \texttt{list} of \texttt{S4} objects of class \texttt{Message} \\ \hline \end{tabular} \end{small} \caption{\label{table-get-types}Correspondence between field type and R type retrieved by the extractors. \footnotesize{1. R lacks native 64-bit integers, so the \texttt{RProtoBuf.int64AsString} option is available to return large integers as characters to avoid losing precision. This option is described in Section~\ref{sec:int64}}. R also lacks an unsigned integer type.} \end{table} ### Modify fields \label{Message-method-setfield} The \verb|$<-| and \verb|[[<-| operators are implemented for \texttt{Message} objects to set the value of a field. The R data is coerced to match the type of the message field. ```{r modify} message <- new(tutorial.Person, name = "foo", id = 2) message$email <- "foo@bar.com" message[["id"]] <- 42 message[[1]] <- "foobar" cat(message$as.character()) ``` Table~\ref{table-message-field-setters} describes the R types that are allowed in the right hand side depending on the target type of the field. \begin{table}[h] \centering \begin{small} \begin{tabular}{|p{5cm}|p{7cm}|} \hline internal type & allowed R types \\ \hline \hline \texttt{double}, \texttt{float} & \texttt{integer}, \texttt{raw}, \texttt{double}, \texttt{logical} \\ \hline \texttt{int32}, \texttt{int64}, \texttt{uint32}, \texttt{uint64}, \texttt{sint32}, \texttt{sint64}, \texttt{fixed32}, \texttt{fixed64}, \texttt{sfixed32}, \texttt{sfixed64} & \texttt{integer}, \texttt{raw}, \texttt{double}, \texttt{logical}, \texttt{character} \\ \hline \texttt{bool} & \texttt{integer}, \texttt{raw}, \texttt{double}, \texttt{logical} \\ \hline \texttt{bytes}, \texttt{string} & \texttt{character} \\ \hline \texttt{enum} & \texttt{integer}, \texttt{double}, \texttt{raw}, \texttt{character} \\ \hline \texttt{message}, \texttt{group} & \texttt{S4}, of class \texttt{Message} of the appropriate message type, or a \texttt{list} of \texttt{S4} objects of class \texttt{Message} of the appropriate message type.\\ \hline \end{tabular} \end{small} \caption{\label{table-message-field-setters}Allowed R types depending on internal field types. } \end{table} ### Message\$has method \label{Message-method-has} The \texttt{has} method indicates if a field of a message is set. For repeated fields, the field is considered set if there is at least on object in the array. For non-repeated fields, the field is considered set if it has been initialized. The \texttt{has} method is a thin wrapper around the \texttt{HasField} and \texttt{FieldSize} methods of the \texttt{google::protobuf::Reflection} C++ class. ```{r has} message <- new(tutorial.Person, name = "foo") message$has("name") message$has("id") message$has("phone") ``` ### Message\$clone method \label{Message-method-clone} The \texttt{clone} function creates a new message that is a clone of the message. This function is a wrapper around the methods \texttt{New} and \texttt{CopyFrom} of the \texttt{google::protobuf::Message} C++ class. ```{r methodclone} m1 <- new(tutorial.Person, name = "foo") m2 <- m1$clone() m2$email <- "foo@bar.com" cat(as.character(m1)) cat(as.character(m2)) ``` ### Message\$isInitialized method \label{Message-method-isInitialized} The \texttt{isInitialized} method quickly checks if all required fields have values set. This is a thin wrapper around the \texttt{IsInitialized} method of the \texttt{google::protobuf::Message} C++ class. ```{r methodisinit} message <- new(tutorial.Person, name = "foo") message$isInitialized() message$id <- 2 message$isInitialized() ``` ### Message\$serialize method \label{Message-method-serialize} The \texttt{serialize} method can be used to serialize the message as a sequence of bytes into a file or a binary connection. ```{r messageserialize1} message <- new(tutorial.Person, name = "foo", email = "foo@bar.com", id = 2) tf1 <- tempfile() tf1 message$serialize(tf1) tf2 <- tempfile() tf2 con <- file(tf2, open = "wb") message$serialize(con) close(con) ``` The (temporary) files `tf1` and `tf2` both contain the message payload as a sequence of bytes. The \texttt{readBin} function can be used to read the files as a raw vector in R: ```{r messageserialize2} readBin(tf1, raw(0), 500) readBin(tf2, raw(0), 500) ``` The \texttt{serialize} method can also be used to directly retrieve the payload of the message as a raw vector: ```{r messageserialize3} message$serialize(NULL) ``` ### Message\$clear method \label{Message-method-clear} The \texttt{clear} method can be used to clear all fields of a message when used with no argument, or a given field. ```{r messageclear} message <- new(tutorial.Person, name = "foo", email = "foo@bar.com", id = 2) cat(as.character(message)) message$clear() cat(as.character(message)) message <- new(tutorial.Person, name = "foo", email = "foo@bar.com", id = 2) message$clear("id") cat(as.character(message)) ``` The \texttt{clear} method is a thin wrapper around the \texttt{Clear} method of the \texttt{google::protobuf::Message} C++ class. ### Message\$size method \label{Message-method-size} The \texttt{size} method is used to query the number of objects in a repeated field of a message : ```{r messagesize} message <- new(tutorial.Person, name = "foo", phone = list(new(tutorial.Person.PhoneNumber, number = "+33(0)...", type = "HOME"), new(tutorial.Person.PhoneNumber, number = "+33(0)###", type = "MOBILE") )) message$size("phone") size( message, "phone") ``` The \texttt{size} method is a thin wrapper around the \texttt{FieldSize} method of the \texttt{google::protobuf::Reflection} C++ class. ### Message\$bytesize method \label{Message-method-bytesize} The \texttt{bytesize} method retrieves the number of bytes the message would take once serialized. This is a thin wrapper around the \texttt{ByteSize} method of the \texttt{google::protobuf::Message} C++ class. ```{r messagebytesize} message <- new(tutorial.Person, name = "foo", email = "foo@bar.com", id = 2) message$bytesize() bytesize(message) length(message$serialize(NULL)) ``` ### Message\$swap method \label{Message-method-swap} The \texttt{swap} method can be used to swap elements of a repeated field. ```{r messageswap} message <- new(tutorial.Person, name = "foo", phone = list(new(tutorial.Person.PhoneNumber, number = "+33(0)...", type = "HOME" ), new(tutorial.Person.PhoneNumber, number = "+33(0)###", type = "MOBILE" ))) message$swap("phone", 1, 2) cat(as.character(message$phone[[1]])) cat(as.character(message$phone[[2]])) swap(message, "phone", 1, 2) cat(as.character(message$phone[[1]])) cat(as.character(message$phone[[2]])) ``` ### Message\$set method \label{Message-method-set} The \texttt{set} method can be used to set values of a repeated field. ```{r messagset} message <- new(tutorial.Person, name = "foo", phone = list(new(tutorial.Person.PhoneNumber, number = "+33(0)...", type = "HOME"), new(tutorial.Person.PhoneNumber, number = "+33(0)###", type = "MOBILE"))) number <- new(tutorial.Person.PhoneNumber, number = "+33(0)---", type = "WORK") message$set("phone", 1, number) cat(as.character( message)) ``` ### Message\$fetch method \label{Message-method-fetch} The \texttt{fetch} method can be used to get values of a repeated field. ```{r messagefetch} message <- new(tutorial.Person, name = "foo", phone = list(new(tutorial.Person.PhoneNumber, number = "+33(0)...", type = "HOME"), new(tutorial.Person.PhoneNumber, number = "+33(0)###", type = "MOBILE" ))) message$fetch("phone", 1) ``` ### Message\$setExtension method \label{Message-method-setExtension} The \texttt{setExtension} method can be used to set an extension field of the Message. ```{r messageset} if (!exists("protobuf_unittest.TestAllTypes", "RProtoBuf:DescriptorPool")) { unittest.proto.file <- system.file("unitTests", "data", "unittest.proto", package="RProtoBuf") readProtoFiles(file=unittest.proto.file) } ## Test setting a singular extensions. test <- new(protobuf_unittest.TestAllExtensions) test$setExtension(protobuf_unittest.optional_int32_extension, as.integer(1)) ``` ### Message\$getExtension method \label{Message-method-getExtension} The \texttt{getExtension} method can be used to get values of an extension. ```{r messagegetextension} test$getExtension(protobuf_unittest.optional_int32_extension) ``` ### Message\$add method \label{Message-method-add} The \texttt{add} method can be used to add values to a repeated field. ```{r messageadd} message <- new(tutorial.Person, name = "foo") phone <- new(tutorial.Person.PhoneNumber, number = "+33(0)...", type = "HOME") message$add("phone", phone) cat(message$toString()) ``` ### Message\$str method \label{Message-method-str} The \texttt{str} method gives the R structure of the message. This is rarely useful. ```{r messagestr} message <- new(tutorial.Person, name = "foo", email = "foo@bar.com", id = 2) message$str() str(message) ``` ### Message\$as.character method \label{Message-method-ascharacter} The \texttt{as.character} method gives the debug string of the message. ```{r messageascharacter} message <- new(tutorial.Person, name = "foo", email = "foo@bar.com", id = 2) cat(message$as.character()) cat(as.character(message)) ``` ### Message\$toString method \label{Message-method-toString} \texttt{toString} currently is an alias to the \texttt{as.character} function. ```{r messagetostring} message <- new(tutorial.Person, name = "foo", email = "foo@bar.com", id = 2) cat(message$toString()) cat(toString( message)) ``` ### Message\$as.list method \label{Message-method-aslist} The \texttt{as.list} method converts the message to a named R list. ```{r messageaslist} message <- new(tutorial.Person, name = "foo", email = "foo@bar.com", id = 2) as.list(message) ``` The names of the list are the names of the declared fields of the message type, and the content is the same as can be extracted with the \verb|$| operator described in section~\ref{Message-method-getfield}. ### Message\$update method \label{Message-method-update} The \texttt{update} method can be used to update several fields of a message at once. ```{r messageupdate} message <- new(tutorial.Person) update(message, name = "foo", id = 2, email = "foo@bar.com") cat(message$as.character()) ``` ### Message\$descriptor method \label{Message-method-descriptor} The \texttt{descriptor} method retrieves the descriptor of a message. See section~\ref{subsec-descriptor} for more information about message type descriptors. ```{r messagedescriptor} message <- new(tutorial.Person) message$descriptor() descriptor(message) ``` ### Message\$fileDescriptor method \label{Message-method-fileDescriptor} The \texttt{fileDescriptor} method retrieves the file descriptor of the descriptor associated with a message. See section~\ref{subsec-fileDescriptor} for more information about file descriptors. ```{r messagefiledesc} message <- new(tutorial.Person) message$fileDescriptor() fileDescriptor(message) ``` ## Message descriptors \label{subsec-descriptor} Message descriptors are represented in R with the \emph{Descriptor} S4 class. The class contains the slots \texttt{pointer} and \texttt{type} : \begin{table}[h] \centering \begin{tabular}{|cp{10cm}|} \hline \textbf{slot} & \textbf{description} \\ \hline \texttt{pointer} & external pointer to the \texttt{Descriptor} object of the C++ proto library. Documentation for the \texttt{Descriptor} class is available from the protocol buffer project page: \url{http://code.google.com/apis/protocolbuffers/docs/reference/cpp/google.protobuf.descriptor.html#Descriptor} \\ \hline \texttt{type} & fully qualified path of the message type. \\ \hline \end{tabular} \caption{\label{Descriptor-class-table}Description of slots for the \texttt{Descriptor} S4 class} \end{table} Similarly to messages, the \verb|$| operator can be used to extract information from the descriptor, or invoke pseudo-methods. Table~\ref{Descriptor-methods-table} describes the methods defined for the \texttt{Descriptor} class : \begin{table}[h] \centering \begin{small} \begin{tabular}{|ccp{8cm}|} \hline \textbf{Method} & \textbf{Section} & \textbf{Description} \\ \hline \hline \texttt{new} & \ref{Descriptor-method-new} & Creates a prototype of a message described by this descriptor.\\ \texttt{read} & \ref{Descriptor-method-read} & Reads a message from a file or binary connection.\\ \texttt{readASCII} & \ref{Descriptor-method-readASCII} & Read a message in ASCII format from a file or text connection.\\ \hline \texttt{name} & \ref{Descriptor-method-name} & Retrieve the name of the message type associated with this descriptor.\\ \texttt{as.character} & \ref{Descriptor-method-ascharacter} & character representation of a descriptor\\ \texttt{toString} & \ref{Descriptor-method-tostring} & character representation of a descriptor (same as \texttt{as.character}) \\ \texttt{as.list} & \ref{Descriptor-method-aslist} & return a named list of the field, enum, and nested descriptors included in this descriptor.\\ \texttt{asMessage} & \ref{Descriptor-method-asmessage} & return DescriptorProto message. \\ \hline \texttt{fileDescriptor} & \ref{Descriptor-method-filedescriptor} & Retrieve the file descriptor of this descriptor.\\ \texttt{containing\_type} & \ref{Descriptor-method-containingtype} & Retrieve the descriptor describing the message type containing this descriptor.\\ \texttt{field\_count} & \ref{Descriptor-method-fieldcount} & Return the number of fields in this descriptor.\\ \texttt{field} & \ref{Descriptor-method-field} & Return the descriptor for the specified field in this descriptor.\\ \texttt{nested\_type\_count} & \ref{Descriptor-method-nestedtypecount} & The number of nested types in this descriptor.\\ \texttt{nested\_type} & \ref{Descriptor-method-nestedtype} & Return the descriptor for the specified nested type in this descriptor.\\ \texttt{enum\_type\_count} & \ref{Descriptor-method-enumtypecount} & The number of enum types in this descriptor.\\ \texttt{enum\_type} & \ref{Descriptor-method-enumtype} & Return the descriptor for the specified enum type in this descriptor.\\ \hline \end{tabular} \end{small} \caption{\label{Descriptor-methods-table}Description of methods for the \texttt{Descriptor} S4 class} \end{table} ### Extracting descriptors The \verb|$| operator, when used on a descriptor object retrieves descriptors that are contained in the descriptor. This can be a field descriptor (see section~\ref{subsec-field-descriptor} ), an enum descriptor (see section~\ref{subsec-enum-descriptor}) or a descriptor for a nested type ```{r extractingdescriptors} # field descriptor tutorial.Person$email # enum descriptor tutorial.Person$PhoneType # nested type descriptor tutorial.Person$PhoneNumber # same as tutorial.Person.PhoneNumber ``` ### The new method \label{Descriptor-method-new} The \texttt{new} method creates a prototype of a message described by the descriptor. ```{r newmethod} tutorial.Person$new() new(tutorial.Person) ``` Passing additional arguments to the method allows directly setting the fields of the message at construction time. ```{r newmethod2} tutorial.Person$new(email = "foo@bar.com") # same as update(tutorial.Person$new(), email = "foo@bar.com") ``` ### The read method \label{Descriptor-method-read} The \texttt{read} method is used to read a message from a file or a binary connection. ```{r readmethod} # start by serializing a message message <- new(tutorial.Person.PhoneNumber, type = "HOME", number = "+33(0)....") tf <- tempfile() serialize(message, tf) # now read back the message m <- tutorial.Person.PhoneNumber$read(tf) cat(as.character(m)) m <- read( tutorial.Person.PhoneNumber, tf) cat(as.character(m)) ``` ### The readASCII method \label{Descriptor-method-readASCII} The \texttt{readASCII} method is used to read a message from a text file or a character vector. ```{r readasciimethod} # start by generating the ASCII representation of a message text <- as.character(new(tutorial.Person, id=1, name="Murray")) text # Then read the ascii representation in as a new message object. msg <- tutorial.Person$readASCII(text) ``` ### The toString method \label{Descriptor-method-tostring} \texttt{toString} currently is an alias to the \texttt{as.character} function. ### The as.character method \label{Descriptor-method-ascharacter} \texttt{as.character} prints the text representation of the descriptor as it would be specified in the \texttt{.proto} file. ```{r ascharactermethod} desc <- tutorial.Person cat(desc$toString()) cat(toString(desc)) cat(as.character(tutorial.Person)) ``` ### The as.list method \label{Descriptor-method-aslist} The \texttt{as.list} method returns a named list of the field, enum, and nested descriptors included in this descriptor. ```{r aslisttmethod} tutorial.Person$as.list() ``` ### The asMessage method \label{Descriptor-method-asmessage} The \texttt{asMessage} method returns a message of type \texttt{google.protobuf.DescriptorProto} of the Descriptor. ```{r asmessagemethod} tutorial.Person$asMessage() ``` ### The fileDescriptor method \label{Descriptor-method-filedescriptor} The \texttt{fileDescriptor} method retrieves the file descriptor of the descriptor. See section~\ref{subsec-fileDescriptor} for more information about file descriptors. ```{r asfiledescmethod} desc <- tutorial.Person desc$fileDescriptor() fileDescriptor(desc) ``` ### The name method \label{Descriptor-method-name} The \texttt{name} method can be used to retrieve the name of the message type associated with the descriptor. ```{r namemethod} # simple name tutorial.Person$name() # name including scope tutorial.Person$name(full = TRUE) ``` ### The containing_type method \label{Descriptor-method-containingtype} The \texttt{containing\_type} method retrieves the descriptor describing the message type containing this descriptor. ```{r containingtypemethod} tutorial.Person$containing_type() tutorial.Person$PhoneNumber$containing_type() ``` ### The field_count method \label{Descriptor-method-fieldcount} The \texttt{field\_count} method retrieves the number of fields in this descriptor. ```{r fieldcountmethod} tutorial.Person$field_count() ``` ### The field method \label{Descriptor-method-field} The \texttt{field} method returns the descriptor for the specified field in this descriptor. ```{r fieldmethod} tutorial.Person$field(1) ``` ### The nested_type_count method \label{Descriptor-method-nestedtypecount} The \texttt{nested\_type\_count} method returns the number of nested types in this descriptor. ```{r nestedtypecountmethod} tutorial.Person$nested_type_count() ``` ### The nested_type method \label{Descriptor-method-nestedtype} The \texttt{nested\_type} method returns the descriptor for the specified nested type in this descriptor. ```{r nestedtypemethod} tutorial.Person$nested_type(1) ``` ### The enum_type_count method \label{Descriptor-method-enumtypecount} The \texttt{enum\_type\_count} method returns the number of enum types in this descriptor. ```{r enumtypecountmethod} tutorial.Person$enum_type_count() ``` ### The enum_type method \label{Descriptor-method-enumtype} The \texttt{enum\_type} method returns the descriptor for the specified enum type in this descriptor. ```{r enumtypemethod} tutorial.Person$enum_type(1) ``` ## Field descriptors} \label{subsec-field-descriptor} The class \emph{FieldDescriptor} represents field descriptor in R. This is a wrapper S4 class around the \texttt{google::protobuf::FieldDescriptor} C++ class. Table~\ref{fielddescriptor-methods-table} describes the methods defined for the \texttt{FieldDescriptor} class. \begin{table}[h] \centering \begin{tabular}{|cp{10cm}|} \hline \textbf{slot} & \textbf{description} \\ \hline \texttt{pointer} & External pointer to the \texttt{FieldDescriptor} C++ variable \\ \hline \texttt{name} & simple name of the field \\ \hline \texttt{full\_name} & fully qualified name of the field \\ \hline \texttt{type} & name of the message type where the field is declared \\ \hline \end{tabular} \caption{\label{FieldDescriptor-class-table}Description of slots for the \texttt{FieldDescriptor} S4 class} \end{table} \begin{table}[h] \centering \begin{small} \begin{tabular}{|ccp{8cm}|} \hline \textbf{method} & \textbf{section} & \textbf{description} \\ \hline \hline \texttt{as.character} & \ref{fielddescriptor-method-ascharacter} & character representation of a descriptor\\ \texttt{toString} & \ref{fielddescriptor-method-tostring} & character representation of a descriptor (same as \texttt{as.character}) \\ \texttt{asMessage} & \ref{fielddescriptor-method-asmessage} & return FieldDescriptorProto message. \\ \texttt{name} & \ref{fielddescriptor-method-name} & Return the name of the field descriptor.\\ \texttt{fileDescriptor} & \ref{fielddescriptor-method-filedescriptor} & Return the fileDescriptor where this field is defined.\\ \texttt{containing\_type} & \ref{fielddescriptor-method-containingtype} & Return the containing descriptor of this field.\\ \texttt{is\_extension} & \ref{fielddescriptor-method-isextension} & Return TRUE if this field is an extension.\\ \texttt{number} & \ref{fielddescriptor-method-number} & Gets the declared tag number of the field.\\ \texttt{type} & \ref{fielddescriptor-method-type} & Gets the type of the field.\\ \texttt{cpp\_type} & \ref{fielddescriptor-method-cpptype} & Gets the C++ type of the field.\\ \texttt{label} & \ref{fielddescriptor-method-label} & Gets the label of a field (optional, required, or repeated).\\ \texttt{is\_repeated} & \ref{fielddescriptor-method-isrepeated} & Return TRUE if this field is repeated.\\ \texttt{is\_required} & \ref{fielddescriptor-method-isrequired} & Return TRUE if this field is required.\\ \texttt{is\_optional} & \ref{fielddescriptor-method-isoptional} & Return TRUE if this field is optional.\\ \texttt{has\_default\_value} & \ref{fielddescriptor-method-hasdefaultvalue} & Return TRUE if this field has a default value.\\ \texttt{default\_value} & \ref{fielddescriptor-method-defaultvalue} & Return the default value.\\ \texttt{message\_type} & \ref{fielddescriptor-method-messagetype} & Return the message type if this is a message type field.\\ \texttt{enum\_type} & \ref{fielddescriptor-method-enumtype} & Return the enum type if this is an enum type field.\\ \hline \end{tabular} \end{small} \caption{\label{fielddescriptor-methods-table}Description of methods for the \texttt{FieldDescriptor} S4 class} \end{table} ### The as.character method \label{fielddescriptor-method-ascharacter} The \texttt{as.character} method gives the debug string of the field descriptor. ```{r ascharactermethod2} cat(as.character(tutorial.Person$PhoneNumber)) ``` ### The toString method \label{fielddescriptor-method-tostring} \texttt{toString} is an alias of \texttt{as.character}. ```{r tostringmethod2} cat(tutorial.Person.PhoneNumber$toString()) ``` ### The asMessage method \label{fielddescriptor-method-asmessage} The \texttt{asMessage} method returns a message of type \texttt{google.protobuf.FieldDescriptorProto} of the FieldDescriptor. ```{r asmessagemethod2} tutorial.Person$id$asMessage() cat(as.character(tutorial.Person$id$asMessage())) ``` ### The name method \label{fielddescriptor-method-name} The \texttt{name} method can be used to retrieve the name of the field descriptor. ```{r namemethod2} # simple name. name(tutorial.Person$id) # name including scope. name(tutorial.Person$id, full=TRUE) ``` ### The fileDescriptor method \label{fielddescriptor-method-filedescriptor} The \texttt{fileDescriptor} method can be used to retrieve the file descriptor of the field descriptor. ```{r filedescriptormethod2} fileDescriptor(tutorial.Person$id) tutorial.Person$id$fileDescriptor() ``` ### The containing\_type method \label{fielddescriptor-method-containingtype} The \texttt{containing\_type} method can be used to retrieve the descriptor for the message type that contains this descriptor. ```{r containingtypemethod2} containing_type(tutorial.Person$id) tutorial.Person$id$containing_type() ``` ### The is_extension method \label{fielddescriptor-method-isextension} The \texttt{is\_extension} method returns TRUE if this field is an extension. ```{r isextensionsmethod2} is_extension( tutorial.Person$id ) tutorial.Person$id$is_extension() ``` ### The number method \label{fielddescriptor-method-number} The \texttt{number} method returns the declared tag number of this field. ```{r numbermethod2} number( tutorial.Person$id ) tutorial.Person$id$number() ``` ### The type method \label{fielddescriptor-method-type} The \texttt{type} method can be used to retrieve the type of the field descriptor. ```{r typemethod2} type( tutorial.Person$id ) tutorial.Person$id$type() ``` ### The cpp_type method \label{fielddescriptor-method-cpptype} The \texttt{cpp\_type} method can be used to retrieve the C++ type of the field descriptor. ```{r cpptypemethod2} cpp_type( tutorial.Person$id ) tutorial.Person$id$cpp_type() ``` ### The label method \label{fielddescriptor-method-label} Gets the label of a field (optional, required, or repeated). The \texttt{label} method returns the label of a field (optional, required, or repeated). By default it returns a number value, but the optional \texttt{as.string} argument can be provided to return a human readable string representation. ```{r labelmethod2} label(tutorial.Person$id) label(tutorial.Person$id, TRUE) tutorial.Person$id$label(TRUE) ``` ### The is_repeated method \label{fielddescriptor-method-isrepeated} The \texttt{is\_repeated} method returns TRUE if this field is repeated. ```{r isrepeatedmethod2} is_repeated( tutorial.Person$id ) tutorial.Person$id$is_repeated() ``` ### The is_required method \label{fielddescriptor-method-isrequired} The \texttt{is\_required} method returns TRUE if this field is required. ```{r isrequiredmethod2} is_required( tutorial.Person$id ) tutorial.Person$id$is_required() ``` ### The is_optional method \label{fielddescriptor-method-isoptional} The \texttt{is\_optional} method returns TRUE if this field is optional. ```{r isoptionalmethod2} is_optional(tutorial.Person$id) tutorial.Person$id$is_optional() ``` ### The has_default_value method \label{fielddescriptor-method-hasdefaultvalue} The \texttt{has\_default\_value} method returns TRUE if this field has a default value. ```{r hasdefaultvaluemethod2} has_default_value(tutorial.Person$PhoneNumber$type) has_default_value(tutorial.Person$PhoneNumber$number) ``` ### The default_value method \label{fielddescriptor-method-defaultvalue} The \texttt{default\_value} method returns the default value of a field. ```{r defaultvaluemethod2} default_value(tutorial.Person$PhoneNumber$type) default_value(tutorial.Person$PhoneNumber$number) ``` ### The message_type method \label{fielddescriptor-method-messagetype} The \texttt{message\_type} method returns the message type if this is a message type field. ```{r messagetypemethod2} message_type(tutorial.Person$phone) tutorial.Person$phone$message_type() ``` ### The enum_type method \label{fielddescriptor-method-enumtype} The \texttt{enum\_type} method returns the enum type if this is an enum type field. ```{r enumtypemethod2} enum_type(tutorial.Person$PhoneNumber$type) ``` ## Eenum descriptors \label{subsec-enum-descriptor} The class \emph{EnumDescriptor} is an R wrapper class around the C++ class \texttt{google::protobuf::EnumDescriptor}. Table~\ref{enumdescriptor-methods-table} describes the methods defined for the \texttt{EnumDescriptor} class. \begin{table}[h] \centering \begin{tabular}{|cp{10cm}|} \hline \textbf{slot} & \textbf{description} \\ \hline \texttt{pointer} & External pointer to the \texttt{EnumDescriptor} C++ variable \\ \hline \texttt{name} & simple name of the enum \\ \hline \texttt{full\_name} & fully qualified name of the enum \\ \hline \texttt{type} & name of the message type where the enum is declared \\ \hline \end{tabular} \caption{\label{EnumDescriptor-class-table}Description of slots for the \texttt{EnumDescriptor} S4 class} \end{table} \begin{table}[h] \centering \begin{small} \begin{tabular}{|ccp{8cm}|} \hline \textbf{method} & \textbf{section} & \textbf{description} \\ \hline \hline \texttt{as.list} & \ref{enumdescriptor-method-aslist} & return a named integer vector with the values of the enum and their names.\\ \texttt{as.character} & \ref{enumdescriptor-method-ascharacter} & character representation of a descriptor\\ \texttt{toString} & \ref{enumdescriptor-method-tostring} & character representation of a descriptor (same as \texttt{as.character}) \\ \texttt{asMessage} & \ref{enumdescriptor-method-asmessage} & return EnumDescriptorProto message. \\ \texttt{name} & \ref{enumdescriptor-method-name} & Return the name of the enum descriptor.\\ \texttt{fileDescriptor} & \ref{enumdescriptor-method-filedescriptor} & Return the fileDescriptor where this field is defined.\\ \texttt{containing\_type} & \ref{enumdescriptor-method-containingtype} & Return the containing descriptor of this field.\\ \texttt{length} & \ref{enumdescriptor-method-length} & Return the number of constants in this enum.\\ \texttt{has} & \ref{enumdescriptor-method-has} & Return TRUE if this enum contains the specified named constant string.\\ \texttt{value\_count} & \ref{enumdescriptor-method-valuecount} & Return the number of constants in this enum (same as \texttt{length}).\\ \texttt{value} & \ref{enumdescriptor-method-value} & Return the EnumValueDescriptor of an enum value of specified index, name, or number.\\ \hline \end{tabular} \end{small} \caption{\label{enumdescriptor-methods-table}Description of methods for the \texttt{EnumDescriptor} S4 class} \end{table} ### Extracting descriptors The \verb|$| operator, when used on a EnumDescriptor object retrieves EnumValueDescriptors that are contained in the descriptor. ```{r extractingdescriptors2} tutorial.Person$PhoneType$WORK name(tutorial.Person$PhoneType$value(number=2)) ``` ### The as.list method \label{enumdescriptor-method-aslist} The \texttt{as.list} method creates a named R integer vector that captures the values of the enum and their names. ```{r aslistmethod3} as.list(tutorial.Person$PhoneType) ``` ### The as.character method \label{enumdescriptor-method-ascharacter} The \texttt{as.character} method gives the debug string of the enum type. ```{r ascharactermethod3} cat(as.character(tutorial.Person$PhoneType )) ``` ### The toString method \label{enumdescriptor-method-tostring} The \texttt{toString} method gives the debug string of the enum type. ```{ tostringmethod3} cat(toString(tutorial.Person$PhoneType)) ``` ### The asMessage method \label{enumdescriptor-method-asmessage} The \texttt{asMessage} method returns a message of type \texttt{google.protobuf.EnumDescriptorProto} of the EnumDescriptor. ```{r asmessagemethod3} tutorial.Person$PhoneType$asMessage() cat(as.character(tutorial.Person$PhoneType$asMessage())) ``` ### The name method \label{enumdescriptor-method-name} The \texttt{name} method can be used to retrieve the name of the enum descriptor. ```{r namemethod3} # simple name. name( tutorial.Person$PhoneType ) # name including scope. name( tutorial.Person$PhoneType, full=TRUE ) ``` ### The fileDescriptor method \label{enumdescriptor-method-filedescriptor} The \texttt{fileDescriptor} method can be used to retrieve the file descriptor of the enum descriptor. ```{r filedescriptormethod3} fileDescriptor(tutorial.Person$PhoneType) tutorial.Person$PhoneType$fileDescriptor() ``` ### The containing_type method \label{enumdescriptor-method-containingtype} The \texttt{containing\_type} method can be used to retrieve the descriptor for the message type that contains this enum descriptor. ```{r containing_typemethod3} tutorial.Person$PhoneType$containing_type() ``` ### The length method \label{enumdescriptor-method-length} The \texttt{length} method returns the number of constants in this enum. ```{r lengthmethod3} length(tutorial.Person$PhoneType) tutorial.Person$PhoneType$length() ``` ### The has method \label{enumdescriptor-method-has} The \texttt{has} method returns TRUE if this enum contains the specified named constant string. ```{r hasmethod3} tutorial.Person$PhoneType$has("WORK") tutorial.Person$PhoneType$has("nonexistant") ``` ### The value_count method \label{enumdescriptor-method-valuecount} The \texttt{value\_count} method returns the number of constants in this enum. ```{r value_countmethod3} value_count(tutorial.Person$PhoneType) tutorial.Person$PhoneType$value_count() ``` ### The value method \label{enumdescriptor-method-value} The \texttt{value} method extracts an EnumValueDescriptor. Exactly one argument of 'index', 'number', or 'name' must be specified to identify which constant is desired. ```{r valuemethod3} tutorial.Person$PhoneType$value(1) tutorial.Person$PhoneType$value(name="HOME") tutorial.Person$PhoneType$value(number=1) ``` ## Enum value descriptors \label{subsec-EnumValueDescriptor} The class \emph{EnumValueDescriptor} is an R wrapper class around the C++ class \texttt{google::protobuf::EnumValueDescriptor}. Table~\ref{enumvaluedescriptor-methods-table} describes the methods defined for the \texttt{EnumValueDescriptor} class. \begin{table}[h] \centering \begin{tabular}{|cp{10cm}|} \hline \textbf{slot} & \textbf{description} \\ \hline \texttt{pointer} & External pointer to the \texttt{EnumValueDescriptor} C++ variable \\ \hline \texttt{name} & simple name of the enum value \\ \hline \texttt{full\_name} & fully qualified name of the enum value \\ \hline \end{tabular} \caption{\label{EnumValueDescriptor-class-table}Description of slots for the \texttt{EnumValueDescriptor} S4 class} \end{table} \begin{table}[h] \centering \begin{small} \begin{tabular}{|ccp{8cm}|} \hline \textbf{method} & \textbf{section} & \textbf{description} \\ \hline \hline \texttt{number} & \ref{enumvaluedescriptor-method-number} & return the number of this EnumValueDescriptor. \\ \texttt{name} & \ref{enumvaluedescriptor-method-name} & Return the name of the enum value descriptor.\\ \texttt{enum\_type} & \ref{enumvaluedescriptor-method-enumtype} & return the EnumDescriptor type of this EnumValueDescriptor. \\ \texttt{as.character} & \ref{enumvaluedescriptor-method-ascharacter} & character representation of a descriptor. \\ \texttt{toString} & \ref{enumvaluedescriptor-method-tostring} & character representation of a descriptor (same as \texttt{as.character}). \\ \texttt{asMessage} & \ref{enumvaluedescriptor-method-asmessage} & return EnumValueDescriptorProto message. \\ \hline \end{tabular} \end{small} \caption{\label{enumvaluedescriptor-methods-table}Description of methods for the \texttt{EnumValueDescriptor} S4 class} \end{table} ### The number method \label{enumvaluedescriptor-method-number} The \texttt{number} method can be used to retrieve the number of the enum value descriptor. ```{r numbermethod4} number(tutorial.Person$PhoneType$value(number=2)) ``` ### The name method \label{enumvaluedescriptor-method-name} The \texttt{name} method can be used to retrieve the name of the enum value descriptor. ```{r namemethod4} # simple name. name(tutorial.Person$PhoneType$value(number=2)) # name including scope. name(tutorial.Person$PhoneType$value(number=2), full=TRUE) ``` ### The enum_type method \label{enumvaluedescriptor-method-enumtype} The \texttt{enum\_type} method can be used to retrieve the EnumDescriptor of the enum value descriptor. ```{r enum_typemethod4} enum_type(tutorial.Person$PhoneType$value(number=2)) ``` ### The as.character method \label{enumvaluedescriptor-method-ascharacter} The \texttt{as.character} method gives the debug string of the enum value type. ```{r as.charactermethod4} cat(as.character(tutorial.Person$PhoneType$value(number=2))) ``` ### The toString method \label{enumvaluedescriptor-method-tostring} The \texttt{toString} method gives the debug string of the enum value type. ```{r tostringmethod4} cat(toString(tutorial.Person$PhoneType$value(number=2))) ``` ### The asMessage method \label{enumvaluedescriptor-method-asmessage} The \texttt{asMessage} method returns a message of type \texttt{google.protobuf.EnumValueDescriptorProto} of the EnumValueDescriptor. ```{r asmessagemethod4} tutorial.Person$PhoneType$value(number=2)$asMessage() cat(as.character(tutorial.Person$PhoneType$value(number=2)$asMessage())) ``` ## File descriptors \label{subsec-fileDescriptor} File descriptors describe a whole \texttt{.proto} file and are represented in R with the \emph{FileDescriptor} S4 class. The class contains the slots \texttt{pointer}, \texttt{filename}, and \texttt{package} : \begin{table}[h] \centering \begin{tabular}{|cp{10cm}|} \hline \textbf{slot} & \textbf{description} \\ \hline \texttt{pointer} & external pointer to the \texttt{FileDescriptor} object of the C++ proto library. Documentation for the \texttt{FileDescriptor} class is available from the protocol buffer project page: \url{http://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.descriptor.html#FileDescriptor} \\ \hline \texttt{filename} & fully qualified pathname of the \texttt{.proto} file.\\ \hline \texttt{package} & package name defined in this \texttt{.proto} file.\\ \hline \end{tabular} \caption{\label{FileDescriptor-class-table}Description of slots for the \texttt{FileDescriptor} S4 class} \end{table} Similarly to messages, the \verb|$| operator can be used to extract fields from the file descriptor (in this case, types defined in the file), or invoke pseudo-methods. Table~\ref{filedescriptor-methods-table} describes the methods defined for the \texttt{FileDescriptor} class. ```{r filedescriptorssubsection} f <- tutorial.Person$fileDescriptor() f f$Person ``` \begin{table}[h] \centering \begin{small} \begin{tabular}{|ccp{8cm}|} \hline \textbf{method} & \textbf{section} & \textbf{description} \\ \hline \hline \texttt{name} & \ref{filedescriptor-method-name} & Return the filename for this FileDescriptorProto.\\ \texttt{package} & \ref{filedescriptor-method-package} & Return the file-level package name specified in this FileDescriptorProto.\\ \texttt{as.character} & \ref{filedescriptor-method-ascharacter} & character representation of a descriptor. \\ \texttt{toString} & \ref{filedescriptor-method-tostring} & character representation of a descriptor (same as \texttt{as.character}). \\ \texttt{asMessage} & \ref{filedescriptor-method-asmessage} & return FileDescriptorProto message. \\ \texttt{as.list} & \ref{filedescriptor-method-aslist} & return named list of descriptors defined in this file descriptor.\\ \hline \end{tabular} \end{small} \caption{\label{filedescriptor-methods-table}Description of methods for the \texttt{FileDescriptor} S4 class} \end{table} ### The as.character method \label{filedescriptor-method-ascharacter} The \texttt{as.character} method gives the debug string of the file descriptor. ```{r as.charactermethod5} cat(as.character(fileDescriptor(tutorial.Person))) ``` ### The toString method \label{filedescriptor-method-tostring} \texttt{toString} is an alias of \texttt{as.character}. ```{r tostringmethod5} cat(fileDescriptor(tutorial.Person)$toString()) ``` ### The asMessage method \label{filedescriptor-method-asmessage} The \texttt{asMessage} method returns a protocol buffer message representation of the file descriptor. ```{r asmessagemethod5} asMessage(tutorial.Person$fileDescriptor()) cat(as.character(asMessage(tutorial.Person$fileDescriptor()))) ``` ### The as.list method \label{filedescriptor-method-aslist} The \texttt{as.list} method creates a named R list that contains the descriptors defined in this file descriptor. ```{r as.listmethod5} as.list(tutorial.Person$fileDescriptor()) ``` ### The name method \label{filedescriptor-method-name} The \texttt{name} method can be used to retrieve the file name associated with the file descriptor. The optional boolean argument can be specified if full pathnames are desired. ```{r namemethod5} name(tutorial.Person$fileDescriptor()) tutorial.Person$fileDescriptor()$name(TRUE) ``` ### The package method \label{filedescriptor-method-package} The \texttt{package} method can be used to retrieve the package scope associated with this file descriptor. ```{r packagemethod5} tutorial.Person$fileDescriptor()$package() ``` ## Service descriptors \label{subsec-ServiceDescriptor} Not fully implemented. Needs to be connected to a concrete RPC implementation. The Google Protocol Buffers C++ open-source library does not include an RPC implementation, but this can be connected easily to others. ### The method descriptors method \label{subsec-MethodDescriptor} Not fully implemented. Needs to be connected to a concrete RPC implementation. The Google Protocol Buffers C++ open-source library does not include an RPC implementation, but this can be connected easily to others. Now that Google [gRPC](https://grpc.io/) is released, this an obvious possibility. Contributions would be most welcome. # Utilities ## Ccoercing objects to messages The \texttt{asMessage} function uses the standard coercion mechanism of the \texttt{as} method, and so can be used as a shorthand : ```{r coerceobjectstomessage} # coerce a message type descriptor to a message asMessage(tutorial.Person) # coerce a enum descriptor asMessage(tutorial.Person.PhoneType) # coerce a field descriptor asMessage(tutorial.Person$email) # coerce a file descriptor asMessage(fileDescriptor(tutorial.Person)) ``` ## Completion The \texttt{RProtoBuf} package implements the \texttt{.DollarNames} S3 generic function (defined in the \texttt{utils} package) for all classes. Completion possibilities include pseudo method names for all classes, plus : \begin{itemize} \item field names for messages \item field names, enum types, nested types for message type descriptors \item names for enum descriptors \item names for top-level extensions \item message names for file descriptors \end{itemize} In the unlikely event that there is a user-defined field of exactly the same name as one of the pseudo methods, the user-defined field shall take precedence for completion purposes by design, since the method name can always be invoked directly. ## with and within The S3 generic \texttt{with} function is implemented for class \texttt{Message}, allowing to evaluate an R expression in an environment that allows to retrieve and set fields of a message simply using their names. ```{r withwithin message <- new(tutorial.Person, email = "foo```### The com" method with(message, { ## set the id field id <- 2 ## set the name field from the email field name <- gsub( "[@]", " ", email ) sprintf( "%d [%s] : %s", id, email, name ) }) ``` The difference between \texttt{with} and \texttt{within} is the value that is returned. For \texttt{with} returns the result of the R expression, for \texttt{within} the message is returned. In both cases, the message is modified because \texttt{RProtoBuf} works by reference. ## identical The \texttt{identical} method is implemented to compare two messages. ```{r identical} m1 <- new(tutorial.Person, email = "foo@bar.com", id = 2) m2 <- update(new(tutorial.Person) , email = "foo@bar.com", id = 2) identical(m1, m2) ``` The \verb|==| operator can be used as an alias to \texttt{identical}. ```{r equalforidentical} m1 == m2 m1 != m2 ``` Alternatively, the \texttt{all.equal} function can be used, allowing a tolerance when comparing \texttt{float} or \texttt{double} values. ## merge \texttt{merge} can be used to merge two messages of the same type. ```{r merge} m1 <- new(tutorial.Person, name = "foobar") m2 <- new(tutorial.Person, email = "foo@bar.com") m3 <- merge(m1, m2) cat(as.character(m3)) ``` ## P The \texttt{P} function is an alternative way to retrieve a message descriptor using its type name. It is not often used because of the lookup mechanism described in section~\ref{sec-lookup}. ```{r P} P("tutorial.Person") new(P("tutorial.Person")) # but we can do this instead tutorial.Person new(tutorial.Person) ``` # Advanced Features ## Extensions \label{sec-extensions} Extensions allow you to declare a range of field numbers in a message that are available for extension types. This allows others to declare new fields for a given message type possibly in their own \texttt{.proto} files without having to edit the original file. See \url{https://developers.google.com/protocol-buffers/docs/proto#extensions}. Notice that the last line of the \texttt{Person} message schema in \texttt{addressbook.proto} is the following line : ``` extensions 100 to 199; ``` This specifies that other users in other .proto files can use tag numbers between 100 and 199 for extension types of this message. ## Descriptor lookup \label{sec-lookup} The \texttt{RProtoBuf} package uses the user defined tables framework that is defined as part of the \texttt{RObjectTables} package available from the OmegaHat project. The feature allows \texttt{RProtoBuf} to install the special environment \emph{RProtoBuf:DescriptorPool} in the R search path. The environment is special in that, instead of being associated with a static hash table, it is dynamically queried by R as part of R's usual variable lookup. In other words, it means that when the R interpreter looks for a binding to a symbol (foo) in its search path, it asks to our package if it knows the binding "foo", this is then implemented by the \texttt{RProtoBuf} package by calling an internal method of the \texttt{protobuf} C++ library. ## 64-bit integer issues \label{sec:int64} R does not have native 64-bit integer support. Instead, R treats large integers as doubles which have limited precision. For example, it loses the ability to distinguish some distinct integers: ```{r 64bitex} 2^53 == (2^53 + 1) ``` Protocol Buffers are frequently used to pass data between different systems, however, and most other systems these days have support for 64-bit integers. To work around this, RProtoBuf allows users to get and set 64-bit integer types by treating them as characters when running on a platform with a 64-bit long long type available. ```{r 64bitex2, echo=FALSE} if (!exists("protobuf_unittest.TestAllTypes", "RProtoBuf:DescriptorPool")) { unittest.proto.file <- system.file("unitTests", "data", "unittest.proto", package="RProtoBuf") readProtoFiles(file=unittest.proto.file) } ``` If we try to set an int64 field in R to double values, we lose precision: ## Deprecated Feature: Protocol Buffer Groups \label{sec:groups} Groups are a deprecated feature that offered another way to nest information in message definitions. For example, the \texttt{TestAllTypes} message type in \texttt{unittest.proto} includes an OptionalGroup type: ```cpp optional group OptionalGroup = 16 { optional int32 a = 17; } ``` And although the feature is deprecated, it can be used with RProtoBuf: ```{r groupsfeature} test <- new(protobuf_unittest.TestAllTypes) test$optionalgroup$a <- 3 test$optionalgroup$a cat(as.character(test)) ``` Note that groups simply combine a nested message type and a field into a single declaration. The field type is OptionalGroup in this example, and the field name is converted to lower-case 'optionalgroup' so as not to conflict with the type name. Note that groups simply combine a nested message type and a field into a single declaration. The field type is OptionalGroup in this example, and the field name is converted to lower-case 'optionalgroup' so as not to conflict with the type name. # Other approaches Saptarshi Guha wrote another package that deals with integration of Protocol Buffer messages with R, taking a different angle: serializing any R object as a message, based on a single catch-all \texttt{proto} file. Saptarshi's package is available at \url{http://ml.stat.purdue.edu/rhipe/doc/html/ProtoBuffers.html}. Jeroen Ooms took a similar approach influenced by Saptarshi in his \texttt{RProtoBufUtils} package. Unlike Saptarshi's package, RProtoBufUtils depends on RProtoBuf for underlying message operations. This package is available at \url{https://github.com/jeroenooms/RProtoBufUtils}. # Plans for future releases Protocol Buffers have a mechanism for remote procedure calls (RPC) that is not yet used by \texttt{RProtoBuf}, but we may one day take advantage of this by writing a Protocol Buffer message R server, and client code as well, probably based on the functionality of the \texttt{Rserve} package. Now that Google [gRPC](https://grpc.io/) is released, this an obvious possibility. Contributions would be most welcome. Extensions have been implemented in RProtoBuf and have been extensively used and tested, but they are not currently described in this vignette. Additional examples and documentation are needed for extensions. # Acknowedgements Some of the design of the package is based on the design of the \texttt{rJava} package by Simon Urbanek (dispatch on `new`, S4 class structures using external pointers, etc). We would like to thank Simon for his indirect involvment on \texttt{RProtoBuf}. The user defined table mechanism, implemented by Duncan Temple Lang for the purpose of the \texttt{RObjectTables} package allowed the dynamic symbol lookup (see section~\ref{sec-lookup}). Many thanks to Duncan for this amazing feature. \renewcommand{\pnasbreak}{\begin{strip}\vskip0pt\end{strip}} \newpage RProtoBuf/vignettes/inactive/0000755000176200001440000000000013005133352015741 5ustar liggesusersRProtoBuf/vignettes/inactive/Makefile.in0000644000176200001440000000275113005133352020013 0ustar liggesusers ## this is a 'fake' all as R-devel gets a race condition on RProtoBuf-intro and deletes the .tex file all: RProtoBuf-unitTests.pdf RProtoBuf-quickref.pdf ## 'real all' pdfall: RProtoBuf-unitTests.pdf RProtoBuf-intro.pdf RProtoBuf-quickref.pdf pdfclean: rm -fr *.pdf clean: rm -f RProtoBuf-intro.aux RProtoBuf-intro.log RProtoBuf-intro.out rm -f RProtoBuf-quickref.aux RProtoBuf-quickref.log RProtoBuf-quickref.out rm -f RProtoBuf-unitTests.aux RProtoBuf-unitTests.log RProtoBuf-unitTests.out rm -rf auto/ setvars: R_HOME= @R_HOME@ RPROG= $(R_HOME)/bin/R RSCRIPT=$(R_HOME)/bin/Rscript RProtoBuf-unitTests.pdf: unitTests/RProtoBuf-unitTests.R $(RSCRIPT) --default-packages="RProtoBuf,Rcpp,brew,RUnit,tools,utils" unitTests/RProtoBuf-unitTests.R RProtoBuf-intro.pdf: RProtoBuf/RProtoBuf.Rnw cp -f RProtoBuf/RProtoBuf.Rnw RProtoBuf-intro.Rnw $(RSCRIPT) -e "require('highlight'); require('tools'); Sweave('RProtoBuf-intro.Rnw', driver=HighlightWeaveLatex()); texi2dvi('RProtoBuf-intro.tex', pdf=TRUE, clean=TRUE)" cp -f RProtoBuf/RProtoBuf-fake.Rnw RProtoBuf-intro.Rnw RProtoBuf-quickref.pdf: RProtoBuf-quickref/RProtoBuf-quickref.Rnw touch RProtoBuf-quickref.Rnw rm RProtoBuf-quickref.Rnw cp -f RProtoBuf-quickref/RProtoBuf-quickref.Rnw . $(RSCRIPT) -e "require( 'highlight'); require('tools'); Sweave('RProtoBuf-quickref.Rnw', driver=HighlightWeaveLatex()); texi2dvi('RProtoBuf-quickref.tex', pdf=TRUE, clean=TRUE)" cp -f RProtoBuf-quickref/RProtoBuf-quickref-fake.Rnw RProtoBuf-quickref.Rnw RProtoBuf/vignettes/inactive/static-use.Rnw0000644000176200001440000001270113005133352020513 0ustar liggesusers% % This has been removed from the vignette because the corresponding % functionality is no longer in the package % \section{Static use: Revisiting the tutorial} In this section, we illustrate use of Protocol Buffers in a \textsl{static} fashion: based on the \texttt{proto} file, code is generated by the compiler and used by language-specific bindings. \subsection{The address book example} Through this document, we will use the \texttt{addressbook} example that is used by the official tutorials for Java, Python and C++. It is based on the following \texttt{proto} file: <>= ab.proto <- system.file( "proto", "addressbook.proto", package = "RProtoBuf" ) writeLines( readLines( ab.proto ) ) @ The \texttt{proto} file defines : \begin{itemize} \item three message types \begin{itemize} \item \texttt{tutorial.Person}, \item \texttt{tutorial.Person.PhoneNumber} and \item \texttt{tutorial.AddressBook} \end{itemize} \item an enum type \texttt{tutorial.Person.PhoneType} with three values \texttt{MOBILE}, \texttt{HOME} and \texttt{WORK} \end{itemize} We see that a message type can contain several different items: \begin{itemize} \item sets of fields---for example the \texttt{Person} message type contains the required field \texttt{name} of primitive type \texttt{string} associated with the tag number 1; \item fields can be either required (as \texttt{name} or \texttt{id}) or optional (as \texttt{email}); \item other message type descriptions---\texttt{Person} contains the nested message type \texttt{PhoneNumber}; hence the fully qualified type of \texttt{PhoneNumber} is \texttt{tutorial.Person.PhoneNumber} \item enum type descriptions. \end{itemize} Using the \texttt{protoc} compiler, we can generate functions that access these Protocol Buffer messages and their components for both reading and writing using any of the three officially supported languages C++, Java and Python. For example, for C++ the call \begin{quote} \texttt{protoc --cpp\_out=. addressbook.proto} \end{quote} generates almost eighteen hundreed lines of code: seven hundred in a header file \texttt{addressbook.pb.h} and almost elevenhundred in a file \texttt{addressbook.pb.cc}. These two files are used in the tutorial application programs \texttt{add\_person.cc} and \texttt{list\_people.cc}. The former adds a new record to an address book defined by the \texttt{proto} file shown above, and the latter prints the contents of all records in the address book. \subsection{Simple R accessors for the address book example} The Protocol Buffers tutorial contains two simple standalone programs to, respectively, add a record and list all records from an address book as defined by the \texttt{proto} file shown above. In order to ease the transition from C++ to R when working with Protocol Buffers, we implemented two simple wrapper functions in C++ that accomplish essentially the same task, but are callable directly from R. This use the \texttt{Rcpp} package for interfacing C++ from R. \subsubsection*{Adding a record: \texttt{addPerson()}} The R function \texttt{addPerson()} accepts five arguments: <<>>= args( addPerson ) @ The first argument denotes the (binary) file into which the new address book record will be written. The next four argument describe the record to be added. Both \texttt{id} and \texttt{name} have to be of length one, whereas \texttt{emails} and \texttt{phones} can be of length zero as they correspond to optional fields. The actual implementation in C++ is close to the tutorial example and can be used as gentle first step in programming with R and Protocol Buffers. \subsubsection*{Listing all records: \texttt{listPeopleAsList()} and \texttt{listPeopleAsDataFrame()}} Displaying the content of an address book defined by the \texttt{proto} file above is straigtforward in the command-line example as records are simply printed to the screen. For our use, these data need to be read from the file and transfered back to R. Given the definition of the \texttt{proto} file, we face an interesting problem: some fields are optional, and some fields can be repeated numerous types. That means our data structure can be textsl{ragged}: the number of entries per record cannot be expected to be constant. Of course, R can handle such dynamic data structures rather easily. One approach is to use lists of lists which is implemented in \texttt{listPeopleasList()} which returns a \texttt{list} object to R with one entry per address book record. Each of these entries is itself a list comprised of two character vectors of length one (name and id) as well as further lists for emails and phone numbers. Similarly, we can use the fact that the id field is key identifying a person and return two \texttt{data.frames} to R that that can then be merged on the id. This allows for both potentially missing entries (as for the optional email fields) as well as repeated fields (as for the phone number records). The R function \texttt{listPeopleAsDataFrame()} implements this approach, and its corresponding C++ function is very close to the tutorial file \texttt{list\_people.cc}. Both these functions show how R can use the C++ code generated by the Protocol Buffers compiler. Binding the generated functions to R is straightforward --- but arguably tedious as new interface code needs to be written manually. But R as is dynamically-typed language, we would like to use Protocol Buffers in a less rigid fashion. The next few sections show how this can be done. RProtoBuf/vignettes/proto/0000755000176200001440000000000013005133352015302 5ustar liggesusersRProtoBuf/vignettes/proto/int64.proto0000644000176200001440000000025113005133352017331 0ustar liggesusers// mark as Protocol Buffers v2 format syntax = "proto2"; package JSSPaper; message Example1 { optional bool optional_bool = 1; repeated int64 repeated_int64 = 2; }RProtoBuf/vignettes/proto/hist.pb0000644000176200001440000000014513005133352016574 0ustar liggesusers ? @ @ @ @#Example Histogram Created in PythonRProtoBuf/README.md0000644000176200001440000000422613164257321013423 0ustar liggesusers## RProtoBuf [![Build Status](https://travis-ci.org/eddelbuettel/rprotobuf.svg)](https://travis-ci.org/eddelbuettel/rprotobuf) [![License](https://eddelbuettel.github.io/badges/GPL2+.svg)](http://www.gnu.org/licenses/gpl-2.0.html) [![CRAN](http://www.r-pkg.org/badges/version/RProtoBuf)](https://cran.r-project.org/package=RProtoBuf) [![Downloads](http://cranlogs.r-pkg.org/badges/RProtoBuf?color=brightgreen)](http://www.r-pkg.org/pkg/RProtoBuf) R Interface to [Google Protocol Buffers](https://developers.google.com/protocol-buffers/) ### What are Protocol Buffers? A serialization format developed by [Google](https://www.google.com) and used widely within Google, and by numerous other projects. Quoting from the [official website](https://developers.google.com/protocol-buffers/): > Protocol buffers are Google's language-neutral, platform-neutral, extensible mechanism for serializing structured data – think XML, but smaller, faster, and simpler. You define how you want your data to be structured once, then you can use special generated source code to easily write and read your structured data to and from a variety of data streams and using a variety of languages. [Protocol Buffers](https://developers.google.com/protocol-buffers/) natively support C++, C#, Go, Java and Python. Many other languages are supported via contributed extensions. This package adds support for [R](https://www.r-project.org). ### Installation You can either install from source via this repo, or install [the CRAN package](https://cran.r-project.org/package=RProtoBuf) the usual way from [R](https://www.r-project.org) via ```r install.packages("RProtoBuf") ``` but do make sure you have the system requirements covered when building from source. Under Debian/Ubuntu you may need ```bash sudo apt-get install protobuf-compiler libprotobuf-dev libprotoc-dev ``` with similar commands on other operating systems or distributions. ### Documentation The package contains two pdf vignettes; the second one corresponds to [our JSS paper](https://www.jstatsoft.org/article/view/v071i02). ### Authors Romain Francois, Dirk Eddelbuettel, Murray Stokely and Jeroen Ooms ### License GPL (>= 2) RProtoBuf/MD50000644000176200001440000003163213164765764012474 0ustar liggesusersba6a3a9d45d8f51fdb759a2b9a23b3e1 *ChangeLog 284bc86547be323cc1857a89cfe6441f *DESCRIPTION 726667551ac0c9267644bcf416e8c3d2 *NAMESPACE 5ca3a0e6f04efd0664fc0238a1afd7bb *R/00classes.R ad31e4eeef1cfcb9e6052da2884bf818 *R/add.R 9d141fa9b6995218d84192f2f8f48313 *R/aslist.R c4ae245b40eee8819918c5763194ad99 *R/clear.R b3b7a9eb09ec909a0b8ca0a2c5451199 *R/clone.R b28d2343dd36ba673299bce87e7f9506 *R/completion.R 38ae44c79783992074c60338c61d02c3 *R/containing_type.R 7e0e0dea56b20f2850a18c6f711c72e0 *R/debug_string.R 7b469c12eecb5782af0255b06cc65009 *R/descriptor.R ed9e4c00923c284134c8e053698fbc0d *R/extensions.R 7b4e29c09e90e8bc12c3c1142a0b136e *R/field_count.R 2a27c0337d136afdbff0fb37edaf8f4e *R/has.R eccf8112b4b4c55e3f63142b8080e779 *R/http.handler.R d13027e3925a54a5ad99ccc25e46b12f *R/identical.R 5aad5f1d7263b6ce452bf07cdb33dc66 *R/initialized.R 07200abda49678e81eb10f8f1bb08fe9 *R/internals.R 0176cbff7f11d23ae2d6de6c57a407af *R/lookup.R 4453435f6ffdf81405768b62736d2280 *R/merge.R 1ae2bff7191f6a042a82d13d8cfa638a *R/read.R 9748d95fb54956ee1202c2a0eb0e576e *R/rexp_obj.R c5136c115d0c052aa3baf378c9d488ca *R/rpc.R d3a77f8815c1665cb7809823c2aade5c *R/serialize.R 1e07553fc771bd00c48378440481ccb4 *R/serialize_pb.R e5e4078bddf3252088482ff7b93109a7 *R/set.R 3147fe08c024da6833e8507161fe40b4 *R/size.R 94d9a6f7d11473f2d933edb6cb343a85 *R/swap.R e403daf56d76175b0dbb779fbf241a12 *R/unit_tests.R d65f4fddc0268d985d9f70577afdd8e6 *R/with.R 3d748318946134e30c89d702056b18df *R/wrapper_CodedInputStream.R 4c905df41ab1daf41f6259c8ab506850 *R/wrapper_CodedOutputStream.R eaeb7ee0e7ea168d4fdc60de5211de30 *R/wrapper_EnumDescriptor.R 0f8b8670532d914e828e84d99923a210 *R/wrapper_EnumValueDescriptor.R 8e2a91b60a9be5ae68160d4b907014da *R/wrapper_FieldDescriptor.R 3836caea68599871649d735dd364ded1 *R/wrapper_MethodDescriptor.R 3e75318bef5d508a5432b4ef972aa106 *R/wrapper_ServiceDescriptor.R 15200614add0962256aba49748578e0d *R/wrapper_ZeroCopyInputStream.R 64270847c9aea97babc5dd667ffa4543 *R/zzz.R 0a7dddaf1478bf6737351c05852168f1 *README cf6b8ff855c0841c836aea7deac22cf0 *README.md 9c2e29fe733b28fbd0058fe8f82a4c86 *TODO a8fa4140f247668857e43c129836c480 *build/vignette.rds 2640d49f49cab982f34888fedcb0f70a *cleanup ed310586a1ca7c22a64dcaeefdb6a45f *configure 91c30e4d3c22c021e8fb94db663c6c5c *configure.ac d41d8cd98f00b204e9800998ecf8427e *configure.win 38719099f12809ebe19a43b951474c6b *demo/00Index 6275f697db7b64510f10f6bbc95c0498 *demo/addressbook.R 81d0dda686db1c07b625f49ea321a0af *demo/io.R 9ed50fca39d7442e4baaf9d24a1b1663 *inst/CITATION 273411932098396c91c89c6a7e9c92e7 *inst/NEWS.Rd 5485d1d9d1bfb19216aaef28bd8fcc89 *inst/THANKS 95e5b805dfed6a58d9341dadfb88d8d1 *inst/doc/RProtoBuf-intro.R 455d1fc9ec66529525b1ab5e5b5e6f55 *inst/doc/RProtoBuf-intro.Rmd bd334891e1a3bfae2afee54c0064d272 *inst/doc/RProtoBuf-intro.pdf b83a107abeb06164684bb49afe5cc130 *inst/doc/RProtoBuf-paper.R 126dcc5fc93ad8be2af332fff046f28c *inst/doc/RProtoBuf-paper.Rnw 8f6b3ef86fa9ffb8030098f32d4b9124 *inst/doc/RProtoBuf-paper.pdf af9e6df38ed571801f9b1b33ab9153d8 *inst/doc/RProtoBuf-quickref.R f531ff7f64dae19f5e59db3b200ea412 *inst/doc/RProtoBuf-quickref.Rmd 5c4de772b48a1b469346abef58345840 *inst/doc/RProtoBuf-quickref.pdf d58f8a01ff830e711be53df88d59d337 *inst/doc/RProtoBuf-unitTests.R 31ab1ab2350cdc2a0a8df9949484302c *inst/doc/RProtoBuf-unitTests.Rnw 284cc8011001c96f090e1d76db54cf31 *inst/doc/RProtoBuf-unitTests.pdf 8513688afa8b8be605c63815fe85dead *inst/examples/addressbook.pb 7f6e97dd4d48fcec1cfd7f9998dc0a62 *inst/opencpu/ocpu-getdata.R f16a4dde30d41003822a89fc99c7be66 *inst/opencpu/ocpu-getdata.py a9db27c47c52780e2fd620644059c6bd *inst/opencpu/ocpu-rpc.R 3de58b5add288354f79acf36a25429c2 *inst/opencpu/ocpu-rpc.py f3af33a40592bb447056578db18dfeee *inst/opencpu/readme.txt 45d4975a534ce2ea5aaf45c502ef4ec3 *inst/opencpu/rexp_pb2.py 9f9089f3b10a48b44260a8bd70db28e1 *inst/proto/addressbook.proto 2a3e35b1bc89e486008c91f67f39a818 *inst/proto/helloworld.proto cee1ab85ab9b103b74e0bf5be25f5cbf *inst/proto/rexp.proto c53fd49e9bd1f270d6fc87c8904866fe *inst/python/readmsg.py b4383797c61d0ec353a7e2ed5d571018 *inst/python/runtest.sh 95732c81a78c63573be5c9f43a36bddd *inst/python/writemsg.R 0d9b5f1be466ff971309ecb2afd30cf4 *inst/unitTests/data/bytes.proto dd450c59db3fd4f402013878edb78d7a *inst/unitTests/data/encoding.proto e78677c37ce64acb1a5d6ce9155ab83a *inst/unitTests/data/int64.ascii edcac7eaf963ab392904f481e616f7a5 *inst/unitTests/data/nested.proto a8a596114f1818d1f507f8f4e6b30c24 *inst/unitTests/data/proto3.proto b8c19dbd11e2a8abd8795191b7aee7cb *inst/unitTests/data/unittest.proto e2af081c633af2731f87220d75873750 *inst/unitTests/data/unittest_import.proto 91222ae4e941fd3069f5668ba95cc93c *inst/unitTests/runTests.R 0cede7a844fab2ec4ea46310dc99f5e6 *inst/unitTests/runit.FieldDescriptor.R 3b7a27dfeddd87644872a3d2da86e7eb *inst/unitTests/runit.addressbook.R 550eed9c5f2cb0821d297335eb171120 *inst/unitTests/runit.bool.R 7590d4026f8a2719a583a5e5d0cb7b0e *inst/unitTests/runit.bytes.R 84dccd99bf99f2eb22684d887b853457 *inst/unitTests/runit.descriptors.R 23242ede8974367485e63df371c883f1 *inst/unitTests/runit.enums.R 72e5bcb33d001a52c05c6e1288a4237d *inst/unitTests/runit.extensions.R 4c34b40a01998144756c638fbc3dc18c *inst/unitTests/runit.extremevalues.R 04fdded1d553b5b040f0d58c646e53b8 *inst/unitTests/runit.golden.message.R 58ff47939b48203884d8c3713139ab35 *inst/unitTests/runit.import.R 0aaef49aff940d809dc88d43f6625e11 *inst/unitTests/runit.int32.R 6b006129c228db1fbe610ce17e03c6cf *inst/unitTests/runit.int64.R a09caadfa8de6700fa169f934e182c4b *inst/unitTests/runit.messages.R 59b793897716193b6a66b437a1c0e332 *inst/unitTests/runit.nested.R e8dcfe0856daf2449ad3fe166674a5f1 *inst/unitTests/runit.proto3.R 16fc6613c0ebdf33c65cf44ecb272de2 *inst/unitTests/runit.serialize.R 1c0bd7e404461bcb0a95e789607f49f2 *inst/unitTests/runit.serialize_pb.R c15537a7222614c37c34b745e6c41b0d *man/ArrayInputStream-class.Rd 40890fed5d4ed64cafc7095aa9a0b46e *man/ArrayInputStream-methods.Rd acb73c235784572d89ea3ca53da8a9a0 *man/ArrayOutputStream-class.Rd 0f2696eff9e3308e2ffea7307dbc769c *man/ArrayOutputStream-methods.Rd 5cb17d6909f88e5aab5887e62cd03e0d *man/BackUp-methods.Rd ec65248e4a40e1f705a69a2e660425cb *man/ByteCount-methods.Rd f6d8ae782a18986ec842ab22c4107f42 *man/ConnectionInputStream-class.Rd 9b86bbf0669b15a1c86a90adbf8784db *man/ConnectionInputStream-methods.Rd 9c1dd1706a12a141a94a7982ca4ac1d0 *man/ConnectionOutputStream-class.Rd 3ef50451a780e5a3573fcf5c89590fda *man/ConnectionOutputStream-methods.Rd 7f87c1bd0b28718934b66ef13eca430c *man/Descriptor-class.Rd b29c09ea587a461f7f6447a8e48b781e *man/EnumDescriptor-class.Rd 978d2d0af7eb0be959ddd47433a781d2 *man/EnumValueDescriptor-class.Rd c719999a64809be361a95ef8ae36c8dd *man/FieldDescriptor-class.Rd 30e2af5f9e7e28ff4101c9c966fa7660 *man/FileDescriptor-class.Rd 426e87b174f2391bf05d02f81d8e466a *man/FileInputStream-class.Rd 8410f4bcb3dd93a643d1817b7cab66b1 *man/FileInputStream-methods.Rd 7d43b247ffd11fe51f3e4b73a8461abf *man/FileOutputStream-class.Rd 6d89722407047c622381b971f70effca *man/FileOutputStream-methods.Rd 359bb4bc81b9ea412fb7fe4248954ff7 *man/GetErrno-methods.Rd 1d6a02513de6128836b2f11252cb6e56 *man/Message-class.Rd d22d70747d8b6a2929054c2b1cb1a5b5 *man/MethodDescriptor-class.Rd a8f24fa648bfa9b4b311086b81d4c81f *man/Next-methods.Rd 29172e33c7df0cdb8df4b4ef43c14134 *man/P.Rd 04c2989db68ada4b236a65ac616bf2f8 *man/RProtoBuf-package.Rd 57818c7bbcf1dc9193a7dc012e1e75af *man/RpcHTTP-class.Rd 5e00d1563140d560193bff4d0fde572c *man/ServiceDescriptor-class.Rd f28fc53c2c8ef8b09f4fae34adf738e8 *man/SetCloseOnDelete-methods.Rd 79b80066abd78e6af423a45407d557e7 *man/Skip-methods.Rd 5b415f7615a6ec1d5d2c8b86ea54dd7f *man/ZeroCopyInputStream-class.Rd d06dce86d6cb521e137dd874ddad9dba *man/ZeroCopyOutputStream-class.Rd 77b86782ed950f7280f48bb1e814cd93 *man/add.Rd bfcd76fc10327e8e559d568a22e399db *man/asMessage.Rd 5a569e9722221656abeaa53e865ac403 *man/aslist.Rd 8fe8a4434b41b7546d3328104177b5bf *man/bytesize.Rd 650fee9155267d10598ca3bfbc30d5b2 *man/clear.Rd ec80b25ba5b04242a998dd4b743c2826 *man/clone.Rd 28e05b535fa45594cbcae8ab58a92e9b *man/completion.Rd 58e6fbab8fa48a76201ce96d3c67feb9 *man/containing_type-methods.Rd 4adb8eb20d5e6c6961e50efc3261f65e *man/descriptor.Rd b0d10473fc610c8763aa8e0822d6d428 *man/enum_type.Rd a5c50110525b52974417e4f4860781fc *man/enum_type_count.Rd ac509f4bcfde554b5541b143122ad49a *man/fetch.Rd 5e6e20abc7caae612d4a5cb0d5aa8f97 *man/field.Rd 29a2f92961280e7ea5105235f05e06d4 *man/field_count.Rd 2abfd8a218be88e5108a048fd2974b01 *man/fileDescriptor.Rd a6160906d90d5e554694b58c44fecd49 *man/has.Rd 5ef2a8e533d4e9a79fb408bb8aaf144d *man/invokeLocally.Rd 9b76094272fe261773739f60443f9bb0 *man/isInitialized.Rd 99613c07ff0d286d571b75052a331f08 *man/is_extension.Rd f3ae2777164af8aaeabf52587913ea03 *man/label.Rd 9b42f851d250af547c5adc6381e3765c *man/merge.Rd 5b4e21d267dde303131629350925e52d *man/name.Rd 1d36ed77357d85fd08bf95d70ebd0763 *man/nested_type.Rd e4b536e4574dfba5c1684dbdadd37000 *man/nested_type_count.Rd 6c281b6344bdaaf719bad2430769f80c *man/number.Rd 8c81a58d60569755860b6e46bc4661d8 *man/read.Rd 7dae59324b3964eb761ca1f2c3ad7095 *man/readASCII.Rd a901910f76ccd642ec89d0c8ff3ff425 *man/readProtoFiles.Rd 9819c09ba88a668ee8285a13b8c17630 *man/serialize_pb.Rd d9b5d35f7caac9c5f3780cd80cb9f180 *man/set.Rd 1f12bd424d135614cbec9d35324b6147 *man/size.Rd 3983a1b4b6b4d817447ad13d79d46228 *man/sizegets.Rd 91518c1eb7f69e439bbe7871cbad5067 *man/swap.Rd 17d0fefcddcd72efcc76a60978bb6b00 *man/type.Rd 5badc02095845ac4e1498539be042e7d *man/with.Rd 544f42fc1c35f1de8d8c2c6fe2bc7c38 *src/ConnectionCopyingInputStream.cpp c308631a6248210e33044f688aef16e7 *src/ConnectionCopyingInputStream.h e9ecde274f161c38541d2e6736a9cd97 *src/ConnectionCopyingOutputStream.cpp 2f7edbd09315738f39a635c991a8c3b0 *src/ConnectionCopyingOutputStream.h 9af4f9491b2b3e5bb9258a7cef42d274 *src/ConnectionInputStream.cpp 6b5497098f3def43a3adf5357cf92d46 *src/ConnectionInputStream.h 7367fe0ccc5c97cb1a98cb38c9fd064d *src/ConnectionOutputStream.cpp 9fe964bff78152777033909f3d8aa4fa *src/ConnectionOutputStream.h e305dc9aeb529084baff92b0e63a640f *src/DescriptorPoolLookup.cpp c8901818b72ca492bd573a0e3f325bac *src/DescriptorPoolLookup.h fe7b7b94b4b7508e2d98747994d39e6d *src/Makevars.in afdc81d92a939bf21b5c9460e45a7472 *src/Makevars.win bff4ec9a30ed33d9e1fb7f2ce9eed810 *src/RSourceTree.cpp a461687b75d8d22e9fd25076b89c71a3 *src/RSourceTree.h 34ae32444850decc880332d95a42b39a *src/RWarningErrorCollector.cpp 761a01e19cfa448dc46555d64b351773 *src/RWarningErrorCollector.h 7a0a19d1f7e7274492e2bc23ed5f6900 *src/RconnectionCopyingInputStream.cpp dffb1dcc72def5105f3c563ca9b6644e *src/RconnectionCopyingInputStream.h 73150dc065408e91a843148b2cfa34b9 *src/RcppMacros.h 568cadf0482951d002c2183cf5415c02 *src/Rcppsupport.h 42b0baefe8adce8cc83c27372889e604 *src/S4_classes.h c9da30f2ded23d5631d1cc1515c6858b *src/ZeroCopyInputStreamWrapper.cpp 303aa1ef2030275d60d8e4bfeffbc4eb *src/ZeroCopyOutputStreamWrapper.cpp 00d70d3ee7758426b43694e94948e994 *src/extensions.cpp 52afd56eaa8013202920fc5be4a4dbe6 *src/extractors.cpp 699307a87cee7adf4a5087b934c27b01 *src/fieldtypes.h d713a56eea4d60644fd419366ef3d9a8 *src/init.c a81bea8fd0b5bec76fadf4c63628de2a *src/lookup.cpp 3406e5f66b1d77ba35ec316cb8608d85 *src/mutators.cpp 8ceaa161b6cd57654c1b2caa56c266f3 *src/rprotobuf.cpp dbc8e4dfe31d0ede0f81d9abf6bf67f5 *src/rprotobuf.h 77dcd57d1827ecc62b6cd8380314e910 *src/streams.cpp 61a9cf9d31a974cffc414370609a000d *src/wrapper_ArrayInputStream.cpp 4d6efb41f45428c4757c1d8cffad6035 *src/wrapper_ArrayOutputStream.cpp 83ccacf307a33ae444dc95db36619a1a *src/wrapper_Descriptor.cpp 7100d8b0a565ca4acaf1e50b03b87540 *src/wrapper_EnumDescriptor.cpp 7c2ce621deacb24c111e8b5a4b651c3c *src/wrapper_EnumValueDescriptor.cpp 62f221cb2ca8b06475595602f350e3d4 *src/wrapper_FieldDescriptor.cpp af9f8878c4741038f39375b2af24abd2 *src/wrapper_FileDescriptor.cpp b67f6ab18ec9182617f8f3a53670c37a *src/wrapper_Message.cpp 34a093d89f713f4e2671045f17a420fb *src/wrapper_MethodDescriptor.cpp 089af3d37d3cbae46098b07ed1425595 *src/wrapper_ServiceDescriptor.cpp 2c1c7ee61c0e6a8f30c291c89b46bf55 *src/wrapper_ZeroCopyInputStream.cpp 6c1d5df84213b965ae16778455090663 *tests/runUnitTests.R eed075d4b6a48c75f369c421cf845a26 *tools/winlibs.R 455d1fc9ec66529525b1ab5e5b5e6f55 *vignettes/RProtoBuf-intro.Rmd 126dcc5fc93ad8be2af332fff046f28c *vignettes/RProtoBuf-paper.Rnw f136387c11a22105eee7371818beacd6 *vignettes/RProtoBuf-paper.bib f531ff7f64dae19f5e59db3b200ea412 *vignettes/RProtoBuf-quickref.Rmd 31ab1ab2350cdc2a0a8df9949484302c *vignettes/RProtoBuf-unitTests.Rnw 9d5a9174a82963f2f51863b2dda63257 *vignettes/figures/HistogramTools.pdf c727d40ae2834f8a34ba8f541ca87544 *vignettes/figures/fig-021.pdf e52fcc72320587205ba44bb0f1e33567 *vignettes/figures/fig-SER.pdf 107256baabac9d3c621424b2eeec97c6 *vignettes/figures/histogram-mapreduce-diag1.pdf b7c0c609a09de939ce648dd0bb9b3d0e *vignettes/figures/protobuf-distributed-system-crop.pdf 9ad30eeb7c977dc76b6788f8c54ecf12 *vignettes/inactive/Makefile.in 814abd89ea166e4d54794d8ddd5197aa *vignettes/inactive/static-use.Rnw abeb4d4272f44405073619ca10820c06 *vignettes/proto/hist.pb 5054f56718b0fe81cd1e5469d1844638 *vignettes/proto/int64.proto RProtoBuf/README0000644000176200001440000000355613005133352013020 0ustar liggesusersQuoting from http://en.wikipedia.org/wiki/Protocol_Buffers Protocol Buffers is a serialization format with an interface description language developed by Google. The original Google implementation for C++, Java and Python is available under a free software, open source license. Various other language implementations are either available or in development. . The design goals for Protocol Buffers emphasized simplicity and performance. In particular, it was designed to be faster than XML (no reproducible comparisons are publicly available to confirm this, however). Protocol Buffers is very similar to Facebook’s Thrift protocol, except it does not include a concrete RPC stack to use for defined services. Since Protocol Buffers was open sourced, a number of RPC stacks have emerged to fill this gap. . Prior to the release as open source, Protocol Buffers had been widely used at Google for storing and interchanging all kinds of structured information. Protocol Buffers serve as a basis for a custom RPC system that is used for practically all inter-machine communication at Google.[1] . Data structures and services are defined in the Proto Definition file (.proto) which is then compiled with protoc. This compilation generates code that matches the services. For example, example.proto will produce example.pb.cc and example.pb.h which will define C++ classes for each Message and Service example.proto defines. . Protocol Buffers allow serialization into any number of formats. In the officially supported implementations there is a full Reflection interface available, making it easy to serialize protos as XML and JSON. . Though the primary purpose of Protocol Buffers is to facilitate network communication, its simplicity and speed make Protocol Buffers a great replacement of data-centric C++ classes and structs. RProtoBuf/build/0000755000176200001440000000000013164671424013243 5ustar liggesusersRProtoBuf/build/vignette.rds0000644000176200001440000000046413164671424015606 0ustar liggesusersՓQO0;Ma=@1X[K năV/,w:GywEk'<_Fd3=~#1T; ͉ Qvlj5sB>*.Bɫ []_%9.LE9OQ&!JB#RProtoBuf/DESCRIPTION0000644000176200001440000000254713164765764013675 0ustar liggesusersPackage: RProtoBuf Version: 0.4.11 Date: 2017-10-03 Author: Romain Francois, Dirk Eddelbuettel, Murray Stokely and Jeroen Ooms Maintainer: Dirk Eddelbuettel Title: R Interface to the 'Protocol Buffers' 'API' (Version 2 or 3) Description: Protocol Buffers are a way of encoding structured data in an efficient yet extensible format. Google uses Protocol Buffers for almost all of its internal 'RPC' protocols and file formats. Additional documentation is available in two included vignettes one of which corresponds to our 'JSS' paper (2016, . Either version 2 or 3 of the 'Protocol Buffers' 'API' is supported. Depends: R (>= 3.0.0), methods Imports: utils, stats, tools, Rcpp, RCurl LinkingTo: Rcpp Suggests: RUnit, rmarkdown, knitr, pinp VignetteBuilder: knitr SystemRequirements: ProtoBuf libraries and compiler version 2.2.0 or later; version 3.0.0 or later is supported as well. On Debian/Ubuntu these can be installed as libprotoc-dev, libprotobuf-dev and protobuf-compiler, while on Fedora/CentOS protobuf-devel and protobuf-compiler are needed. BugReports: https://github.com/eddelbuettel/rprotobuf/issues URL: https://github.com/eddelbuettel/rprotobuf License: GPL (>= 2) NeedsCompilation: yes Packaged: 2017-10-03 11:23:00 UTC; edd Repository: CRAN Date/Publication: 2017-10-03 19:58:44 UTC RProtoBuf/configure0000755000176200001440000044315313164671424014065 0ustar liggesusers#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for RProtoBuf 0.4.10. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='RProtoBuf' PACKAGE_TARNAME='rprotobuf' PACKAGE_VERSION='0.4.10' PACKAGE_STRING='RProtoBuf 0.4.10' PACKAGE_BUGREPORT='' PACKAGE_URL='' # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='LTLIBOBJS LIBOBJS PKG_LIBS PKG_CPPFLAGS R EGREP GREP PROTOC PKGCONFIG ac_ct_CC CFLAGS CC CXXCPP OBJEXT EXEEXT ac_ct_CXX CPPFLAGS LDFLAGS CXXFLAGS CXX target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir runstatedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking ' ac_precious_vars='build_alias host_alias target_alias CXX CXXFLAGS LDFLAGS LIBS CPPFLAGS CCC CXXCPP CC CFLAGS' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -runstatedir | --runstatedir | --runstatedi | --runstated \ | --runstate | --runstat | --runsta | --runst | --runs \ | --run | --ru | --r) ac_prev=runstatedir ;; -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ | --run=* | --ru=* | --r=*) runstatedir=$ac_optarg ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures RProtoBuf 0.4.10 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/rprotobuf] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of RProtoBuf 0.4.10:";; esac cat <<\_ACEOF Some influential environment variables: CXX C++ compiler command CXXFLAGS C++ compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CXXCPP C++ preprocessor CC C compiler command CFLAGS C compiler flags Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to the package provider. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF RProtoBuf configure 0.4.10 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_cxx_try_compile LINENO # ---------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_compile # ac_fn_cxx_try_cpp LINENO # ------------------------ # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_cpp # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_cxx_check_header_mongrel LINENO HEADER VAR INCLUDES # --------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_cxx_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_cxx_check_header_mongrel # ac_fn_cxx_try_run LINENO # ------------------------ # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_cxx_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_run # ac_fn_cxx_check_header_compile LINENO HEADER VAR INCLUDES # --------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_cxx_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_cxx_check_header_compile cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by RProtoBuf $as_me 0.4.10, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # We are using C++ ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu if test -z "$CXX"; then if test -n "$CCC"; then CXX=$CCC else if test -n "$ac_tool_prefix"; then for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CXX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CXX"; then ac_cv_prog_CXX="$CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CXX=$ac_cv_prog_CXX if test -n "$CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 $as_echo "$CXX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CXX" && break done fi if test -z "$CXX"; then ac_ct_CXX=$CXX for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CXX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CXX"; then ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CXX="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CXX=$ac_cv_prog_ac_ct_CXX if test -n "$ac_ct_CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 $as_echo "$ac_ct_CXX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CXX" && break done if test "x$ac_ct_CXX" = x; then CXX="g++" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CXX=$ac_ct_CXX fi fi fi fi # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C++ compiler works" >&5 $as_echo_n "checking whether the C++ compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C++ compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler default output file name" >&5 $as_echo_n "checking for C++ compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C++ compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5 $as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } if ${ac_cv_cxx_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_cxx_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 $as_echo "$ac_cv_cxx_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GXX=yes else GXX= fi ac_test_CXXFLAGS=${CXXFLAGS+set} ac_save_CXXFLAGS=$CXXFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 $as_echo_n "checking whether $CXX accepts -g... " >&6; } if ${ac_cv_prog_cxx_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_cxx_werror_flag=$ac_cxx_werror_flag ac_cxx_werror_flag=yes ac_cv_prog_cxx_g=no CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_cv_prog_cxx_g=yes else CXXFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : else ac_cxx_werror_flag=$ac_save_cxx_werror_flag CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_cv_prog_cxx_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cxx_werror_flag=$ac_save_cxx_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 $as_echo "$ac_cv_prog_cxx_g" >&6; } if test "$ac_test_CXXFLAGS" = set; then CXXFLAGS=$ac_save_CXXFLAGS elif test $ac_cv_prog_cxx_g = yes; then if test "$GXX" = yes; then CXXFLAGS="-g -O2" else CXXFLAGS="-g" fi else if test "$GXX" = yes; then CXXFLAGS="-O2" else CXXFLAGS= fi fi ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5 $as_echo_n "checking how to run the C++ preprocessor... " >&6; } if test -z "$CXXCPP"; then if ${ac_cv_prog_CXXCPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CXXCPP needs to be expanded for CXXCPP in "$CXX -E" "/lib/cpp" do ac_preproc_ok=false for ac_cxx_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CXXCPP=$CXXCPP fi CXXCPP=$ac_cv_prog_CXXCPP else ac_cv_prog_CXXCPP=$CXXCPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5 $as_echo "$CXXCPP" >&6; } ac_preproc_ok=false for ac_cxx_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu if test -z "$CXX"; then if test -n "$CCC"; then CXX=$CCC else if test -n "$ac_tool_prefix"; then for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CXX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CXX"; then ac_cv_prog_CXX="$CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CXX=$ac_cv_prog_CXX if test -n "$CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 $as_echo "$CXX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CXX" && break done fi if test -z "$CXX"; then ac_ct_CXX=$CXX for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CXX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CXX"; then ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CXX="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CXX=$ac_cv_prog_ac_ct_CXX if test -n "$ac_ct_CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 $as_echo "$ac_ct_CXX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CXX" && break done if test "x$ac_ct_CXX" = x; then CXX="g++" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CXX=$ac_ct_CXX fi fi fi fi # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5 $as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } if ${ac_cv_cxx_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_cxx_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 $as_echo "$ac_cv_cxx_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GXX=yes else GXX= fi ac_test_CXXFLAGS=${CXXFLAGS+set} ac_save_CXXFLAGS=$CXXFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 $as_echo_n "checking whether $CXX accepts -g... " >&6; } if ${ac_cv_prog_cxx_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_cxx_werror_flag=$ac_cxx_werror_flag ac_cxx_werror_flag=yes ac_cv_prog_cxx_g=no CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_cv_prog_cxx_g=yes else CXXFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : else ac_cxx_werror_flag=$ac_save_cxx_werror_flag CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_cv_prog_cxx_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cxx_werror_flag=$ac_save_cxx_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 $as_echo "$ac_cv_prog_cxx_g" >&6; } if test "$ac_test_CXXFLAGS" = set; then CXXFLAGS=$ac_save_CXXFLAGS elif test $ac_cv_prog_cxx_g = yes; then if test "$GXX" = yes; then CXXFLAGS="-g -O2" else CXXFLAGS="-g" fi else if test "$GXX" = yes; then CXXFLAGS="-O2" else CXXFLAGS= fi fi ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu ## simpler alternative to test below: AC_PATH_PROG(PROTOC, protoc) # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_PKGCONFIG+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$PKGCONFIG"; then ac_cv_prog_PKGCONFIG="$PKGCONFIG" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_PKGCONFIG="yes" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi PKGCONFIG=$ac_cv_prog_PKGCONFIG if test -n "$PKGCONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKGCONFIG" >&5 $as_echo "$PKGCONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi ## use pkg-config for ProtoBuf settings ## if test x"${PKGCONFIG}" == x"yes"; then if pkg-config --exists protobuf; then protobuf_cxxflags=`pkg-config --cflags protobuf` protobuf_libs=`pkg-config --libs protobuf` else protobuf_cxxflags="" protobuf_libs="-lprotobuf" fi else # Add a reasonable default of -lprotobuf if we don't have pkg-config protobuf_cxxflags="" protobuf_libs="-lprotobuf" fi ## And make sure these flags are used for the tests below. CPPFLAGS="${protobuf_cxxflags} ${CPPFLAGS}" CXXFLAGS="${protobuf_cxxflags} ${CXXFLAGS}" ## look for protoc, the ProtoBuf compiler # Extract the first word of "protoc", so it can be a program name with args. set dummy protoc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_PROTOC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$PROTOC"; then ac_cv_prog_PROTOC="$PROTOC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_PROTOC="yes" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi PROTOC=$ac_cv_prog_PROTOC if test -n "$PROTOC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PROTOC" >&5 $as_echo "$PROTOC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test x"${PROTOC}" == x"no" ; then echo " Your installation does not appear to have protoc installed. Please make sure that you have a working and complete ProtoBuf installation. " exit 1 fi ## look for protobuf headers -- now use pkg-config which even does minimum version ## ## next two lines break witha autoconf 2.65 :-/ #PROTOBUF_VERSION="2.2.0" #PKG_CHECK_MODULES(ProtoBuf, protobuf >= 2.2.0, , AC_MSG_ERROR(Protobuf version 2.2.0 required)) ## check for header and ability to link ## first for headers Debian has in libprotobuf-dev protobuf_common_header=google/protobuf/stubs/common.h protobuf_common_header_cache_var=`$as_echo "ac_cv_header_$protobuf_common_header" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_cxx_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_cxx_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done as_ac_Header=`$as_echo "ac_cv_header_$protobuf_common_header" | $as_tr_sh` ac_fn_cxx_check_header_mongrel "$LINENO" "$protobuf_common_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : else # If it didn't work, try adding /usr/local directly then trying again { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Protobuf headers not found with default CXXFLAGS and CPPFLAGS, manually trying /usr/local/include" >&5 $as_echo "$as_me: WARNING: Protobuf headers not found with default CXXFLAGS and CPPFLAGS, manually trying /usr/local/include" >&2;} CPPFLAGS="${protobuf_cxxflags} ${CPPFLAGS} -I/usr/local/include" CXXFLAGS="${protobuf_cxxflags} ${CXXFLAGS} -I/usr/local/include -L/usr/local/lib" # unset the cache variable for this particular header # check, so we can check again with different defaults # specified. { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unsetting $protobuf_common_header_cache_var" >&5 $as_echo "$as_me: WARNING: Unsetting $protobuf_common_header_cache_var" >&2;} { eval $protobuf_common_header_cache_var=; unset $protobuf_common_header_cache_var;} as_ac_Header=`$as_echo "ac_cv_header_$protobuf_common_header" | $as_tr_sh` ac_fn_cxx_check_header_mongrel "$LINENO" "$protobuf_common_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : else as_fn_error $? "ERROR: ProtoBuf headers required; use '-Iincludedir' in CXXFLAGS for unusual locations." "$LINENO" 5 fi fi ## second for headers Debian has in libprotoc-dev ac_fn_cxx_check_header_mongrel "$LINENO" "google/protobuf/compiler/code_generator.h" "ac_cv_header_google_protobuf_compiler_code_generator_h" "$ac_includes_default" if test "x$ac_cv_header_google_protobuf_compiler_code_generator_h" = xyes; then : else as_fn_error $? "ERROR: ProtoBuf compiler headers required; use '-Iincludedir' in CXXFLAGS for unusual locations." "$LINENO" 5 fi ## third check the lib itself #pb_savedlibs="$LIBS" # LIBS="$LIBS -lprotoc -lprotobuf -lpthread" LIBS="$LIBS $protobuf_libs" ## also check for minimum version { $as_echo "$as_me:${as_lineno-$LINENO}: checking if ProtoBuf version >= 2.2.0" >&5 $as_echo_n "checking if ProtoBuf version >= 2.2.0... " >&6; } if test "$cross_compiling" = yes; then : pb_version_ok=yes else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main() { if (GOOGLE_PROTOBUF_VERSION >= 2001000) { exit (0); } else { exit(1); } } _ACEOF if ac_fn_cxx_try_run "$LINENO"; then : pb_version_ok=yes else pb_version_ok=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi if test x"${pb_version_ok}" == x"no"; then as_fn_error $? "Need ProtoBuf version >= 2.2.0" "$LINENO" 5 else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi # Extract the first word of "R", so it can be a program name with args. set dummy R; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_R+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$R"; then ac_cv_prog_R="$R" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_R="yes" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi R=$ac_cv_prog_R if test -n "$R"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $R" >&5 $as_echo "$R" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi ## With thanks to Kurt : ${R_HOME=`R RHOME`} if test -z "${R_HOME}"; then as_fn_error $? "Could not determine R_HOME." "$LINENO" 5 fi R_CXXFLAGS=`"${R_HOME}/bin/R" CMD config CXXFLAGS` CXXFLAGS="${CXXFLAGS} ${R_CXXFLAGS}" ## now use all these PKG_CPPFLAGS="${PKG_CPPFLAGS} ${CXXFLAGS} ${protobuf_cxxflags}" PKG_LIBS="${PKG_LIBS} ${protobuf_libs}" ac_config_files="$ac_config_files src/Makevars" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Transform confdefs.h into DEFS. # Protect against shell expansion while executing Makefile rules. # Protect against Makefile macro expansion. # # If the first sed substitution is executed (which looks for macros that # take arguments), then branch to the quote section. Otherwise, # look for a macro that doesn't take arguments. ac_script=' :mline /\\$/{ N s,\\\n,, b mline } t clear :clear s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g t quote s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g t quote b any :quote s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g s/\[/\\&/g s/\]/\\&/g s/\$/$$/g H :any ${ g s/^\n// s/\n/ /g p } ' DEFS=`sed -n "$ac_script" confdefs.h` ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by RProtoBuf $as_me 0.4.10, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE Configuration files: $config_files Report bugs to the package provider." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ RProtoBuf config.status 0.4.10 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --he | --h | --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "src/Makevars") CONFIG_FILES="$CONFIG_FILES src/Makevars" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" eval set X " :F $CONFIG_FILES " shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi echo " RProtoBuf $PACKAGE_VERSION ================ cflags: ${PKG_CPPFLAGS} libs: ${PKG_LIBS} " RProtoBuf/ChangeLog0000644000176200001440000026377413164671030013732 0ustar liggesusers2017-10-03 Dirk Eddelbuettel * DESCRIPTION (Version, Date): Release 0.4.11 2017-10-02 Dirk Eddelbuettel * DESCRIPTION: Minor edit to suppress another NOTE from R CMD check * README.md: Idem 2017-10-01 Dirk Eddelbuettel * vignettes/RProtoBuf-intro.Rmd: Renamed, now uses Rmd via pinp * vignettes/RProtoBuf-quickref.Rmd: Idem * DESCRIPTION: Added pinp package, rolled minor version, use doi in Description * cleanup: Adjusted and updated * .travis.yml (install): Add r-cran-pinp 2017-08-26 Dirk Eddelbuettel * .travis.yml (before_install): Use https for curl fetch 2017-08-14 Dirk Eddelbuettel * DESCRIPTION (Version, Date): Roll minor version * src/S4_classes.h: Initialize S4 base class in copy constructor for S4_ArrayOutputStream class 2017-08-13 Dirk Eddelbuettel * DESCRIPTION (Version, Date): Release 0.4.10 * R/00classes.R: Correct one package= arg in .Call to PACKAGE as requested by CRAN * src/init.c: Corresponding change in Descriptor_getField registration * inst/unitTests/runit.import.R (test.import): Test failing import on package's own DESCRIPTION file rather than /etc/hosts 2017-08-01 Jeffrey Shen * R/rexp_obj.R: Check in deserializer if invalid class is set 2017-03-06 Dirk Eddelbuettel * DESCRIPTION (Version, Date): Release 0.4.9 2017-03-05 Dirk Eddelbuettel * DESCRIPTION (Version, Date): Roll minor version and date * src/init.c (R_init_RProtoBuf): Call R_registerRoutines() and R_useDynamicSymbols() * NAMESPACE: Use .registration=TRUE on useDynLib * src/extensions.cpp (rprotobuf): Rename getExtension to getExtension_cpp to disambiguate from R function * src/rprotobuf.cpp (rprotobuf): Idem for readProtoFiles_cpp * R/00classes.R (.icall): Comment-out unused function (setMethod): Remove erroneous extra '...' from Message_clone arguments * R/clone.R (._clone.message): Add missing PACKAGE= argument to .Call * R/extensions.R: Idem * R/has.R (._has_enum_name): Idem * R/internals.R (readProtoFiles): Idem * R/merge.R: Idem * R/with.R (generateActiveBindings): Idem * R/has.R (._has_enum_name): Use PACKAGE= in .Call() 2017-02-26 David Kretch * vignettes/RProtoBuf-intro.Rnw: Several small corrections 2017-01-19 Dirk Eddelbuettel * configure.ac: Renamed from configure.in, minor edit 2017-01-18 Dirk Eddelbuettel * configure.in: Updated and simplified in a few places as we no longer need m4 macros for C++0x or Rscript for Rcpp library query * configure: Re-generated accordingly * src/Makevars.in: Set CXX_STD=CXX11 * m4/m4-ax_cxx_compile_stdcxx_0x.m4: Removed * cleanup: remove autoconf cache 2017-01-17 Dirk Eddelbuettel * DESCRIPTION (Version, Date): Relase 0.4.8 2017-01-16 Dirk Eddelbuettel * DESCRIPTION (Version, Date): Roll minor version and date * tools/winlibs.R: Use proto3 library from rwinlib repo * src/Makevars.win: Update to proto 3.0.0 paths * inst/unitTests/runit.proto3.R: New test file * inst/unitTests/data/proto3.proto: Support for new test file 2016-10-29 Dirk Eddelbuettel * DESCRIPTION (Version, Date): Release 0.4.7 2016-10-24 Dirk Eddelbuettel * DESCRIPTION (Version): Roll minor version and date * src/lookup.cpp: Replace omegahat.org with omagehat.net * vignettes/RProtoBuf-paper.bib: Ditto 2016-09-09 Dirk Eddelbuettel * DESCRIPTION (Version, Date): New release 0.4.6 * README.md: Expanded, added three short sections 2016-09-08 Dirk Eddelbuettel * inst/NEWS.Rd: Ditto, also replace \cpkg{} with \CRANpkg{} * README.md: Use https for CRAN URL 2016-09-06 Dirk Eddelbuettel * vignettes/RProtoBuf-paper.Rnw: Comment-out the use of the \DOI macro from (updated) jss.cls: cannot ship jss.cls (or R will warn) and cannot use \DOI as (as R-release and older do not know \DOI) 2016-09-01 Dirk Eddelbuettel [ Entry for anonymous PR #18 by 'oliverbock' ] * R/rexp_obj.R (unrexp_string): Ensure zero-length strings can be serialized; special case of native encoding for S4 objects * inst/unitTests/runit.serialize_pb.R: New tests 2016-08-29 Dirk Eddelbuettel * DESCRIPTION (Version, Date): New release 0.4.5 2016-08-16 Dirk Eddelbuettel * DESCRIPTION (SystemRequirements): Add explicit note that Protocol Buffers 3.0.0 are supported as well 2016-08-15 Dirk Eddelbuettel * DESCRIPTION (Version): Rolling minor version * inst/proto/addressbook.proto: Added 'syntax = "proto2";' * inst/proto/helloworld.proto: Idem * inst/proto/rexp.proto: Idem * inst/unitTests/data/bytes.proto: Idem * inst/unitTests/data/encoding.proto: Idem * inst/unitTests/data/nested.proto: Idem * inst/unitTests/data/unittest.proto: Idem * inst/unitTests/data/unittest_import.proto: Idem * vignettes/proto/int64.proto: Idem * inst/unitTests/runit.addressbook.R (test.ascii): Comment-out one sub-test concerned with access under bad file modes 2016-08-13 Dirk Eddelbuettel * .travis.yml: Switch to using run.sh for Travis CI, also switch to using a build matrix across ProtoBuf versions 2 and 3 2016-07-19 Craig Radcliffe * configure.in: Make sure that CXXFLAGS is from the environment when writing to src/Makevars 2016-07-10 Dirk Eddelbuettel * DESCRIPTION (Version): Release 0.4.4 * vignettes/RProtoBuf-paper.Rnw: Added, based on pending JSS publication * vignettes/RProtoBuf-paper.bib: Ditto * vignettes/figures/*: Ditto * vignettes/proto/*: Ditto * vignettes/jss.cls: Ditto * vignettes/jss.bst: Ditto * inst/CITATION: Update to version provided by JSS * README.md: Updated to use of canonical URLs for CRAN 2016-05-19 Dirk Eddelbuettel * vignettes/RProtoBuf-unitTests.Rnw: Do not write unit test results to /tmp per request from CRAN to not write outside test directories 2016-04-26 Dirk Eddelbuettel * CONTRIBUTING.md: New workflow document 2016-04-25 Jeroen Ooms * R/rexp_obj.R: Fix zero-length edge case * R/serialize_pb.R: Improved documentation * man/serialize_pb.Rd: Ditto 2016-04-21 Jeroen Ooms * src/Makevars.win: Accomodate new Windows toolchain 2016-04-21 Jonathon Love * inst/unitTests/runit.addressbook.R: Set to mode 0644 * inst/unitTests/runit.bytes.R: Ditto 2016-02-11 Dirk Eddelbuettel * DESCRIPTION (License): Set to GPL (>= 2) which is what the code files with actual copyright and license headers had all along * README.md: Idem 2015-08-25 Dirk Eddelbuettel * DESCRIPTION (Version): Release 0.4.3 2015-08-24 Dirk Eddelbuettel * README.md: Additional badges * inst/unitTests/runit.FieldDescriptor.R: Added msg field 2015-08-23 Dirk Eddelbuettel * tools/winlibs.R: Actually tests against R 3.3.0 2015-08-23 Jeroen Ooms * tools/winlibs.R: Test for R 3.3.0 on Windows 2015-08-23 Dirk Eddelbuettel * NAMESPACE: Added imports for as and is from methods * DESCRIPTION: Removed several of the (largely redundant) URLs, and minor edits in Description: to update to current standard * man/RProtoBuf-package.Rd: Updated, removed old URLs. * .travis.yml: Accelerate by installing dependencies via apt-get 2015-08-05 Balasubramanian Narasimhan * NAMESPACE: Added import for show from methods package 2015-07-08 Jeroen Ooms * tools/winlibs.R: Update URL to windows build of the required ProtoBuf library 2015-01-16 Dirk Eddelbuettel * DESCRIPTION: Minor edits 2015-01-16 Jeroen Ooms * DESCRIPTION: Make SystemRequirements: more explicit 2014-12-11 Jeroen Ooms * DESCRIPTION: Update URLs 2014-12-10 Dirk Eddelbuettel * DESCRIPTION (Version): Release 0.4.2 2014-12-10 Jeroen Ooms * src/Makevars.win: Use new ProtoBuf 2.6.1 builds on Windows * tools/winlibs.R: Helper function used for Windows build * inst/unitTests/runit.int64.R: Fixed a windows bug 2014-12-08 Jeroen Ooms * inst/proto/rexp.proto: Add a new type 'native' * R/rexp_obj.R: Modify (un)serialize_pb to serialize() non-data types as 'native' types 2014-12-04 Dirk Eddelbuettel * .travis.yml: Added after move to GitHub * README.md: Added minimal first version with Travis badge 2014-12-04 Murray Stokely * inst/unitTests/runit.int64.R: restore options on exit from this function to make the test indempotent. 2014-12-01 Dirk Eddelbuettel * man/Message-class.Rd: Completed documentation * man/Descriptor-class.Rd: Ditto * man/EnumDescriptor-class.Rd: Ditto 2014-12-01 Murray Stokely * R/wrapper_ZeroCopyInputStream.R: Avoid file.create for getting absolute path of a temporary file name (JSS reviewer feedback) * R/serialize.R: Idem. 2014-11-26 Murray Stokely Address feedback from anonymous reviewer for JSS to make this package more complete: * inst/unitTests/runit.serialize_pb.R: Add a test to verify that we can serialize all 100+ built-in datasets with R and get an identical object to the original once unserialized. * R/rexp_obj.R: Serialize function, language, and environment objects by just falling back to R's native serialization and using raw bytes to store them. This at least lets us round-trip encode all native R types, even though these three only make sense in the context of R. Greatly simplify the can_serialize_pb function. * inst/proto/rexp.proto: Add support for function, language, and environment objects. 2014-11-25 Dirk Eddelbuettel * vignettes/RProtoBuf-intro.Rnw: Applied a few corrections spotted by Tim Hesterberg and communicated in email. 2014-11-24 Murray Stokely * inst/unitTests/runit.golden.message.R: remove trailing whitespace. * man/P.Rd: Improve output of example. 2014-09-15 Murray Stokely Address feedback from anonymous reviewers for our Journal of Statistical Software submission: * src/wrapper_EnumDescriptor.cpp (rprotobuf): Correct the definition of as.list for EnumDescriptors to return a proper list instead of a named vector. * man/aslist.Rd: clarify order of returned list for descriptor objects. * NAMESPACE: add names as exported method. * R/00classes.R (show): Update the default print methods to use cat() with fill=TRUE instead of show() to eliminate the confusing [1] since the classes in RProtoBuf are not vectorized. * Make Descriptor and EnumDescriptor objects subsettable with "[[". * Add length() method for Descriptor objects. * Add names() method for Message, Descriptor, and EnumDescriptor objects. * inst/unitTests/runit.enums.R (test.enums): Add test of subsetting an EnumDescriptor object. * inst/unitTests/runit.descriptors.R (test.descriptor): Add test for subsetting of descriptor objects. * DESCRIPTION (Version): Increment. 2014-04-02 Murray Stokely Two patches from Karl Millar : * src/S4_classes.h (rprotobuf): Change handling of S4_EnumDescriptor when passed a NULL pointer to just create empty object with empty name and full_name rather than setting to R_NilValue. * src/wrapper_EnumDescriptor.cpp (rprotobuf): Change return value of getValue* functions on EnumDescriptor and return an EnumValueDescriptor or R_NilValue on failure. 2014-04-01 Murray Stokely * tests/runUnitTests.R: Add improved checks to ensure R CMD CHECK fails if there are any errors in the tests, not just failures. 2014-03-25 Dirk Eddelbuettel * DESCRIPTION (Version): Release 0.4.1 2014-03-24 Murray Stokely * inst/unitTests/runit.int64.R (test.int64): Check Rcpp:::capabilities() to ensure we have long long support in Rcpp before trying to run the 64-bit integer tests. * inst/unitTests/data/unittest.proto: Comment out TestEnumWithDupValue. This causes problems with the newest libprotobuf-2.5 which now wants an option to be specified to enable enum aliasing like this. * configure.in: if we can't find the libproto headers with the default CPPFLAGS/CXXFLAGS, manually add /usr/local/include and try again. 2014-03-10 Murray Stokely * src/DescriptorPoolLookup.cpp (rprotobuf): Import all top-level enums defined in an imported .proto file. * src/rprotobuf.cpp (rprotobuf): Add a function to get the enum descriptor associated with a named enum. * inst/unitTests/runit.enums.R (test.enums): Test that we import top-level enums from .proto files correctly. * R/00classes.R (P): Correct a bug in the show() method for EnumDescriptor that prevented useful output in some contexts. 2014-02-21 Murray Stokely * inst/unitTests/runit.messages.R (test.message): Add a test for the deprecated group feature which works fine with RProtoBuf. The type is converted to lower case, which users often forget. * vignettes/RProtoBuf-intro.Rnw (subsection{Deprecated Feature: Protocol Buffer Groups}): document groups. * inst/CITATION: Add a manual CITATION file pointing to the preprint on arxiv.org in addition to the normal auto-generated citation(). 2014-01-19 Dirk Eddelbuettel * DESCRIPTION: Finalize release 0.4.0 with initial Windows support * src/S4_classes.h: Adapt to S4 access function renaming in Rcpp 0.10.7 and later, with special thanks to Kevin Ushey 2014-01-13 Murray Stokely * inst/unitTests/runit.int64.R (test.int64): Skip this test with a warning if running on a machine with sizeof(long long) < 8. * vignettes/RProtoBuf-intro.Rnw (subsection{64-bit integer issues}): Hide 64-bit field accesses with if conditional to avoid running code that won't work on platforms without 64-bit long longs. * DESCRIPTION (Version): Increment to 0.4.0 2014-01-09 Murray Stokely * R/read.R: Add a logical argument 'partial' to readASCII that accepts uninitialized message fragments. * src/wrapper_Descriptor.cpp (rprotobuf): Idem * inst/unitTests/runit.addressbook.R (test.ascii): Add tests for above. 2014-01-04 Murray Stokely * R/wrapper_CodedInputStream.R: Accept numeric size arguments for ReadRaw and ReadString to make this more user friendly for interactive use by calling as.integer() as needed. * R/00classes.R (P): Add missing object prameters in ZeroCopyInputStream calls to ReadRaw and ReadString. * inst/unitTests/data/encoding.proto: Add example messages used in the encoding documentation. * inst/unitTests/runit.serialize.R (test.encoding): Add tests verifying the exact byte serialization as described in the encoding documentation. (test.arrayinputstream): Add new test of ArrayInputStreams. * src/wrapper_ZeroCopyInputStream.cpp (rprotobuf): Add BEGIN/END_RCPP macros to gracefully catch exceptions and return them as R language errors. * src/streams.cpp (rprotobuf): Idem. * man/ArrayInputStream-class.Rd: Add some examples of using ArrayInputStream. 2014-01-04 Dirk Eddelbuettel * src: Deprecate files SocketCopyingInputStream.{cpp,h}, sisocks.h as the current RProtoBuf design does not provide networking capabilities 2013-12-31 Murray Stokely * src/wrapper_Message.cpp: Fix type coercion bug in add() method for uint32s and add a missing break statement that erroneously raised an error when setting some int64 fields. Make more function arguments const and remove a superfluous BEGIN_RCPP/END_RCPP. Also add comment about long-vector support. All of these fixes were highlighted by Flexelint. * inst/unitTests/runit.int64.R (test.int64): Add tests for above. * inst/unitTests/runit.extremevalues.R (test.uint32): Idem. * src/wrapper_FieldDescriptor.cpp (RPB_HANDLE_CASE): Remove unreachable statement in a macro. * src/wrapper_Descriptor.cpp (rprotobuf): Remove unused variable, rename another variable for clarity, and add some TODOs. * src/wrapper_FileDescriptor.cpp (rprotobuf): Idem. * src/DescriptorPoolLookup.cpp (rprotobuf): Remove unreachable statement. * src/extensions.cpp: Remove unused header. * src/mutators.cpp (rprotobuf): Update code to check for Long vectors and use the safer R_xlen_t type everywhere. Protocol Buffers repeated fields seem to be limited to int size indices as with normal R vectors. * src/rprotobuf.h: Idem 2013-12-30 Murray Stokely * inst/unitTests/runit.extremevalues.R (test.uint32): Add test verifying that we can store 2^32 - 1 properly in repeated or optional protobuf fields. * src/extractors.cpp (rprotobuf): Correct handling of uint32 for repeated fields. * src/wrapper_Message.cpp (rprotobuf): Remove Rf_error in favor of Rcpp_error so that we throw an exception and unwind the stack to deallocate objects before jumping to R's error. * src/DescriptorPoolLookup.cpp (rprotobuf): Idem. * R/size.R: Correct an incorrect method name that prevented size<- from working. * man/size.Rd: Document the behavior of size<- * (C++): Ran all the C++ files and most of the headers through clang-format as described in the STYLE file on R-Forge. Basically, we now use 4-char indents and 100-char limit for line wrap. 2013-12-28 Murray Stokely * src/extractors.cpp (rprotobuf): Correct handling of uint32 for single values greater than 2^31 by returning as R numeric types to avoid losing precision since R doesn't have unsigned int types but C++ does. Works around an Rcpp bug https://r-forge.r-project.org/tracker/index.php?func=detail&aid=1360&group_id=155&atid=637 2013-12-27 Murray Stokely * src/mutators.cpp: Refactor setMessageField into four separate functions, correct a few minor typos, and wrap everything in a try/catch block so we catch any exceptions generated by Rcpp::as or other functions and forward it along to an R-language stop() error instead of terminating our R instance. * src/mutators.cpp (rprotobuf): Add more helpful error message specifying which element of a list is of the wrong type, and what the expected type is, when setting a list of messages. * inst/unitTests/runit.messages.R (test.message): Add unit tests for our handling of setting repeated message fields. * src/wrapper_Message.cpp: Add const qualifier to field_desc throughout file. * src/exceptions.cpp: Remove ancient exceptions handling code, migrate codebase to use standard exception classes and helper functions from Rcpp. * R/exceptions.R (throw): idem. 2013-12-26 Murray Stokely * src/mutators.cpp: Support setting int32 values with character vectors of a decimal number, as we do by necessity for int64s. Also, refuse to set non-repeated bools to NA, just as we do for repeated bool fields by raising a stop() error since protocol buffer bools are 2-valued and NA is the third-value of R bools. * inst/unitTests/runit.int32.R (test.int32): Add tests for above. * NAMESPACE: Add missing export for .DollarNames EnumValueDescriptor to allow completion on that class. * R/00classes.R: Update FileDescriptor '$' dispatch to work properly for the names of fields defined in the FileDescriptor, instead of just returning NULL even for types returned by $ completion. * vignettes/RProtoBuf-intro.Rnw (subsubsection{Retrieve fields}): Update the type mapping tables to note that characters can be extracted from 64-bit integer types with the RProtoBuf.int64AsString type and note that int32 and int64 types can be set to character values representing decimal numbers. * TODO: Update todo list. * inst/unitTests/runit.bool.R (test.bool): Add more tests about boolean values, NA handling, etc. 2013-12-23 Murray Stokely * DESCRIPTION (Version): increment. * inst/proto/addressbook.proto: Reserved extension fields in tutorial.Person. * vignettes/RProtoBuf-intro.Rnw (subsection{Extensions}): Added a new section documenting protocol buffer extensions. 2013-12-20 Murray Stokely * R/00classes.R: Correct a bug that incorrectly dispatched as.character() when as.list() was called on Descriptor objects. 2013-12-18 Murray Stokely * R/completion.R (.DollarNames.EnumValueDescriptor): Add $-completion for EnumValueDescriptor and FileDescriptor classes as with other S4 RProtoBuf classes here. * R/00classes.R (P): Ensure that the FileDescriptor $name() method accepts a boolean for full paths just like the generic name() method. * R/wrapper_EnumDescriptor.R: Add better error checking. Expect exceptions if wrong types are provided for arguments rather than just returning NULL. 2013-12-18 Dirk Eddelbuettel * vignettes/RProtoBuf-intro.Rnw: Use with vignette builder * vignettes/RProtoBuf-quickref.Rnw: Idem * vignettes/RProtoBuf-unitTests.Rnw: Rewritten / simplified * DESCRIPTION: Increased dependency to R (>= 3.0.0) * configure.in: No longer create vignettes/Makefile 2013-12-17 Murray Stokely * R/completion.R (.DollarNames.Message): Add missing methods to dollar completion list for Message and Descriptor objects * vignettes/RProtoBuf/RProtoBuf.Rnw (subsection{messages}): Add missing methods to Table 2 (Messages) and add a table and new sections of methods for Descriptor objects. 2013-12-16 Dirk Eddelbuettel * src/rprotobuf.h (RCPP_ENUM_TRAITS): Don't use extern "C" on internal functions returning atomistic or C++ types 2013-12-15 Dirk Eddelbuettel * DESCRIPTION (Version): Release 0.3.2 * tests/runUnitTests.R: Minor rewrite and cleanup from doRUnit.R with a tip of the hat to Murray's version in his HistogramTools package 2013-12-14 Dirk Eddelbuettel * src/lookup.cpp (rprotobuf): Descrictor pools attached directly * R/lookup.R (attachDescriptorPool): No longer attach them here * src/rprotobuf.h: Updated function declaration 2013-12-14 Murray Stokely * src/mutators.cpp (rprotobuf): Fix a bug which incorrectly prevented users from setting raw non-repeated fields under some circumstances. * inst/unitTests/runit.bytes.R (test.all): Verify raw(10) can be set to required bytes fields to verify correct behavior for use case mentioned on rprotobuf-yada list. 2013-11-13 Murray Stokely * R/extensions.R: Give a user friendly error message if someone tries to set an extension to a message of the wrong type instead of causing a C++ check failure that terminates your R session. * inst/unitTests/runit.extensions.R (test.extension): Add test. 2013-10-23 Murray Stokely * src/lookup.cpp (rprotobuf): Remove stop() error in object table assignment as this was causing errors with the '<<-' operator in any code using RProtoBuf. * inst/unitTests/runit.import.R (test.assign.in.global): Add a test for the above. 2013-09-16 Murray Stokely * DESCRIPTION (Version): Increment to 0.3.1.1. * R/00classes.R: Improve show method for EnumValueDescriptor and add enum_type to '$' dispatch. * man/EnumValueDescriptor-class.Rd: Add examples and document missing methods. * src/wrapper_EnumValueDescriptor.cpp (rprotobuf): Add missing enum_type method. * inst/unitTests/runit.enums.R (test.enums): Add more tests. 2013-09-13 Dirk Eddelbuettel * DESCRIPTION (Version): Release 0.3.1 2013-09-13 Murray Stokely * vignettes/Makefile.in: Update configure to output R_HOME to the vignette makefile so we can avoid the use of a non-portable GNU makefile extension here. 2013-09-12 Murray Stokely * src/RcppMacros.h: Add Rcpp compatibility macros which are simplified versions of the now deprecated ones from Rcpp. 2013-09-11 Murray Stokely * configure.in: If pkg-config is not available add -lprotobuf to PKG_LIBS. This makes it easier to install on MacOS X 10.8, for example. 2013-09-06 Murray Stokely * src/rprotobuf.cpp (rprotobuf): Include the name of the field that could not be found in exceptions in getFieldDescriptor (errors from update / new, etc.). 2013-09-03 Murray Stokely * inst/NEWS.Rd: Summarize changes since the last release. * vignettes/RProtoBuf/RProtoBuf.Rnw: Add a new section on 64-bit issues, document the RProtoBuf.int64AsString option, break out the 'other approaches' section from the 'future work', and fix a few typos. 2013-08-30 Dirk Eddelbuettel * NAMESPACE: Import 'file_path_as_absolute' from package tools, and the two functions needed from the RCurl package * R/*R: Updated several files which no longer need 'tools:::' prefix * DESCRIPTION: Updated Depends: and Imports accordingly 2013-08-29 Murray Stokely * R/zzz.R (.onLoad): Rename option controlling int64 handling with package name prefix. * inst/unitTests/runit.int64.R (test.int64): Idem * src/extractors.cpp (rprotobuf): Add templated function to reduce code duplication in last changelist. * src/mutators.cpp (rprotobuf): Idem 2013-08-27 Murray Stokely * src/extractors.cpp (rprotobuf): Add support for a new option("int64AsString") that controls whether extractors for 64-bit integer fields return character strings or use Rcpp's default wrap type which coerces to numeric, possibly losing precision. * R/zzz.R (.onLoad): Initialize options("int64AsString" = FALSE). * src/Rcppsupport.h (rprotobuf): Add RepeatedFieldImporter classes for int64 and uint64 that return strings instead of int64s. * src/mutators.cpp (rprotobuf): Add support for setting int64 fields as R character vectors that are converted to int64 or uint64 C++ types with std::stringstream. This allows the user to get around the lack of 64-bit integer support in R when working interactively with RProtoBufs where a large precision number or identifier needs to be stored. * inst/unitTests/runit.int64.R: Add tests for the above. 2013-08-21 Murray Stokely * inst/unitTests/runit.addressbook.R (test.ascii): Add more tests. * src/wrapper_Descriptor.cpp (rprotobuf): Add better error handling for readASCII of text strings rather than returning an empty proto. * R/extensions.R: Add checks to ensure that a valid extension FieldDescriptor is passed to getExtension and setExtension. * inst/unitTests/runit.int64.R (test.int64): Add a test illustrating how RProtoBuf is broken in handling 64-bit integers (commented out for now). * man/P.Rd: Document behavior for extensions. * inst/unitTests/runit.extensions.R (test.extension): Add more tests. * src/wrapper_Message.cpp (rprotobuf): Add function for returning the number of extensions set in this message, to improve show() output. * src/rprotobuf.cpp (rprotobuf): Add support for looking up extensions by name and returning FieldDescriptors. * R/00classes.R (P): Add support for returning extension descriptors. 2013-07-14 Dirk Eddelbuettel * inst/unitTests/runit.extensions.R (test.extension): Comment-out test for setExtension against enum, at least for now * vignettes/RProtoBuf/RProtoBuf.Rnw: Added Murray to Authors, at last * vignettes/RProtoBuf-unitTests.Rnw: Idem * vignettes/RProtoBuf-quickref/RProtoBuf-quickref.Rnw: Idem 2013-07-13 Murray Stokely * inst/NEWS.Rd: Summarize new features since the last CRAN release last year. * DESCRIPTION: Increment version to 0.3. 2013-07-13 Dirk Eddelbuettel * man/Message-class.Rd: Added \alias entries for getExtension and setExtension * DESCRIPTION: Incremented Version to separate current test builds from previous release * DESCRIPTION: Removed 'MinimumLibProtoVersion: 2002000' which we no longer need as that version of Protocol Buffers was released a rather long time ago * R/zzz.R: Check for minimal version is now commented-out 2013-07-12 Murray Stokely * src/extensions.cpp: Replace custom extractor and mutator with call to existing functions in mutators.cpp and extractors.cpp that can be used for extensions and any other field type. * src/extensions.R: Idem * vignettes/RProtoBuf/RProtoBuf.Rnw: Document getExtension, setExtension methods. * man/Message-class.Rd: Idem * src/rprotobuf.h: Remove unused desc argument to extractFieldAsSEXP. * src/extractors.cpp: Idem * inst/unitTests/runit.extensions.R: Add additional tests for nested enum and message type extensions. 2013-07-11 Murray Stokely * R/extensions.R: Implement getExtension, setExtension methods. * src/extensions.cpp: Implement getExtension, setExtension. * R/set.R: Add a TODO noting these functions are undocumented. * R/00classes.R: Add setExtension, getExtension extractors for message objects. * R/completion.R: Add setExtension, getExtension. * NAMESPACE: Add setExtension, getExtension. * src/DescriptorPoolLookup.cpp: Add top-level extensions to descriptor pool. * src/rprotobuf.h: Add helper function for getting field descriptor objects. * src/wrapper_FileDescriptor.cpp: Add support for extensions to getMemberNames and as_list * src/lookup.cpp: Add support for looking up extensions. * inst/unitTests/runit.extensions.R: Add basic test for the above. 2013-07-10 Murray Stokely * man/aslist.Rd: Document behavior for enum and file descriptors and be more sparing with \dontrun in examples. * man/EnumDescriptor-class.Rd: Be more sparing with \dontrun in examples so we run more test code. * man/add.Rd: Idem * man/clone.Rd: Idem * man/Descriptor-class.Rd: Idem * man/FieldDescriptor-class.Rd: Idem * man/FileDescriptor-class.Rd: Idem * man/is_extension.Rd: Idem * man/label.Rd: Idem * man/Message-class.Rd: Idem * man/number.Rd: Idem * man/P.Rd: Idem * man/readProtoFiles.Rd: Idem * man/type.Rd: Idem * man/with.Rd: Idem * man/RProtoBuf-package.Rd: Idem 2013-07-08 Murray Stokely * R/has.R: add a has method for EnumDescriptor objects to return a logical indicating if the named constant exists or not. * R/00classes.R: fix a typo that prevented the length method from working properly for EnumDescriptor objects. Use this functionality to add the number of constants in the show method for EnumDescriptors. * R/wrapper_EnumValueDescriptor.R: add a number method to return the numeric value of this enum constant. * man/has.Rd: Add example of the above. * man/number.Rd: Add example of the above. * man/EnumDescriptor-class.Rd: Add example of the above. * man/EnumValueDescriptor-class.Rd: Add example of the above. 2013-02-21 Murray Stokely * R/00classes.R: add filename and package slots to FileDescriptor S4 class and provide more user-friendly show() methods for Messages and FileDescriptors that provide more context about the contained data. * src/S4_classes.h: populate package and filename slots when a FileDescriptor is created based on fields from the underlying C++ object. * inst/unitTests/runit.addressbook.R: add a basic test for FileDescriptors. * man/FileDescriptor-class.Rd: document the new slots in FileDescriptor and add examples. 2012-10-03 Murray Stokely * src/mutators.cpp (rprotobuf): Fix bug where LENGTH() is used on non-vectors when setting a repeated message field to a single Message object. This caused non-deterministic behavior after memory was read from a random location. * inst/unitTests/runit.golden.message.R (test.repeatedFields): Add tests for this case. 2012-09-25 Dirk Eddelbuettel * man/is_extension.Rd: Use \dontrun on examples as we cannot reload the same proto file twice * man/label.Rd: Idem * man/number.Rd: Idem * man/type.Rd: Idem 2012-09-24 Murray Stokely * R/has.R: Distinguish between non-existant and not-set fields in a message by returning NULL in the former case. * R/00classes.R: Idem * src/wrapper_Message.cpp (rprotobuf): Idem * inst/unitTests/runit.golden.message.R (test.has): Add test. * man/has.Rd: Add example of the above. 2012-09-21 Murray Stokely * Fix a bug causing segfaults in containing_type(). * R/containing_type.R: Return NULL instead of invalid descriptors when there is no containing type for an object. * src/S4_classes.h: Check for NULL pointers in the contructors for S4_Descriptor and S4_EnumDescriptor as these methods are called on the return value of e.g. containing_type() in the protobuf API without checking the return alue. * man/containing_type-methods.Rd: Add examples section showing cases where there is and is not a containing_type. * inst/unitTests/runit.FieldDescriptor.R (test.FieldDescriptor.class): Add tests for the above. 2012-08-21 Murray Stokely * src/mutators.cpp: Add better input checking when setting an optional field to avoid an uncaught exception that would kill the R session, and add a test. * inst/unitTests/runit.golden.message.R (test.invalidAssignments): Add test for this. 2012-08-18 Dirk Eddelbuettel * Applied two more patches by Murray and Karl: - Make readASCII() more robust to error conditions; adds tests to catch them. - Correct type(), cpp_type(), and label() methods when as.string=TRUE; add unit tests for these methods, add examples to the Rd files for these methods, and adds type and cpp_type to the NAMESPACE file where they were previously absent. 2012-08-09 Dirk Eddelbuettel * Applied two more patches by Murray: - R/wrapper_FieldDescriptor.R: correct more '_' and '__' mismatches - man/*: update manual pages for style, add examples - src/mutators.cpp: fix bug in handling of NA in boolean vectors - inst/unitTests/runit.golden.message.R: add unit test 2012-08-08 Dirk Eddelbuettel * DESCRIPTION: Release 0.2.5 * src/mutators.cpp: Applied patch by Murray to correctly deal with nested protocol buffer definitions * inst/unitTests/runit.nested.R: Added test from Murray * inst/unitTests/data/nested.proto: Nested protbuf def from Murray * R/serialize.R: Added patch by Murray to not serialize uninitalized protocol buffers (with missing required fields) * inst/unitTests/runit.serialize.R: Added tests for this * /man/add.Rd: Add patch by Murray for stylistic improvement and added examples * inst/NEWS.Rd: Converted NEWS file to .Rd format * DESCRIPTION: Changed Maintainer: to single person per CRAN Policy * vignettes/: Moved from inst/doc/ per CRAN Policy 2012-05-15 Dirk Eddelbuettel * DESCRIPTION: Release 0.2.4 * R/zzz.R (.onLoad): pass lib.loc=libname to readProtoFiles * R/internals.R (readProtoFiles): use lib.loc argument * man/readProtoFiles.Rd: Document new lib.loc argument 2012-05-14 Dirk Eddelbuettel * R/lookup.R: comment-out unlockBinding() which R CMD check does not like as it turns out that we do not need it here anyway * inst/unitTests/runit.addressbook.R (test.ascii): Small correction by converting to character before comparing * DESCRIPTION: Remove Depends: on int64 which is no longer used, lower Depends: on Rcpp to 0.9.6 which should be sufficient 2012-05-13 Dirk Eddelbuettel * src/rprotobuf.h: Added '#include ' to make g++-4.7 happy * src/*: Reversed out SVN revisions 426 to 434 related to int64 2012-04-07 Dirk Eddelbuettel * R/zzz.R: Add 'lib.loc=libname' to packageDescription() call as requested by Brian Ripley 2012-03-20 Dirk Eddelbuettel * Applied another patch by Murray: - src/mutators.cpp: Deal with case of repeated strings - inst/unitTests/runit.golden.message.R: test for this case 2011-07-17 Dirk Eddelbuettel * Applied another patch by Murray: - src/wrapper_Descriptor.cpp: Add missing readASCIIFromConnection C++ function that was called in read.R but not defined. - R/read.R: Remove an _ in the readASCII C++ functions to match the naming convention of the other nearby functions. - man/readASCII.Rd: Add examples of ascii export/import of messages. - inst/unitTests/runit.addressbook.R: Add tests of ascii export/import of messages. 2011-07-07 Dirk Eddelbuettel * src/wrapper_FileDescriptor.cpp (rprotobuf): Applied patch by Murray to correct a cut & paste error in variable name 2011-04-12 Dirk Eddelbuettel * DESCRIPTION: Release 0.2.3 2011-04-10 Dirk Eddelbuettel * src/extractors.cpp: Protect UINT64 and INT64 inside of #ifdef test for RCPP_HAS_LONG_LONG_TYPES which we now need for g++ 4.5 or later * src/mutators.cpp: Idem * wrapper_FieldDescriptor.cpp: Idem 2011-04-05 Dirk Eddelbuettel * inst/doc/Makefile: Call R and Rscript relative to R_HOME/bin 2011-04-04 Dirk Eddelbuettel * inst/doc/Makefile: Do not call clean in all target 2011-01-12 Dirk Eddelbuettel * R/with.R: Use envir= argument to eval() 2011-01-11 Dirk Eddelbuettel * DESCRIPTION: Release 0.2.2 * inst/THANKS: Added new file to say Thanks! 2011-01-10 Dirk Eddelbuettel * Applied another patch by Murray Stokely providing: - R/internals.R: generalise readProtoFiles() adding 'pattern' arg - man/readProtoFiles.Rd: documenting new 'pattern' argument - src/DescriptorPoolLookup.cpp: enhanced error message - inst/unitTests/runit.golden.message.R: new unit test for repeated fields fixed (which was issue addressed earlier) - inst/runit.import.R: new unit test for non-existing file 2011-01-07 Dirk Eddelbuettel * Applied patch by Murray Stokely providing all the following: - src/S4_classes.h: new 'name' and 'full_name' slots - R/00classes.R: idem - R/wrapper_EnumDescriptor.R: fix typo now permitting function call - src/wrapper_EnumDescriptor.cpp: add a bounds check - src/wrapper_EnumValueDescriptor.cpp: add a new name method - inst/unitTests/runit.enums.R: add new unit test * man/EnumValueDescriptor-class.Rd: Add documentation for name and full_name 2010-10-20 Dirk Eddelbuettel * inst/doc/Makefile: do not remove the pdf in 'clean' * inst/unitTests/runit.addressbook.R: stick 'book' into global env. 2010-10-18 Dirk Eddelbuettel * DESCRIPTION: Release 0.2.1 * ChangeLog: moved from inst/ * inst/NEWS: moved from top-level to that it gets installed with package 2010-10-13 Dirk Eddelbuettel * src/*: applied patch by Koert Kuipers to support raw bytes * inst/unitTests/runit.bytes.R: also added unit test by Koert 2010-09-11 Dirk Eddelbuettel * DESCRIPTION: Release 0.2.0 2010-09-10 Romain Francois * man/readASCII.Rd: Rd documentation for readASCII 2010-08-20 Romain Francois * R/read/.R: New readASCII method 2010-08-12 Romain Francois * src/*: restore R CMD check 2010-08-04 Dirk Eddelbuettel * inst/unitTests/runit.addressbook.R: start of new unit tests 2010-07-30 Romain Francois * src/*: correct many small errors so that the vignette builds again 2010-02-02 Dirk Eddelbuettel * configure.in: More rigorous checks for ProtoBuf headers, library, mininal version as well as availability of pkg-config. 2010-02-01 Dirk Eddelbuettel * inst/ChangeLog: added 2010-02-01 Romain Francois * Release 0.1-0 * [r274] /pkg/man/RProtoBuf-package.Rd: tidying up * [r273] /pkg/inst/doc/unitTests-results: * [r272] /pkg/inst/doc/unitTests/RProtoBuf-unitTests.R: minor cleanups for the unit test vignette (same as in Rcpp) * [r271] /pkg/DESCRIPTION, /pkg/inst/doc/unitTests/RProtoBuf-unitTests.R: OS_type: unix (for now) * [r270] /pkg/DESCRIPTION: version bump to 0.1-0 * [r269] /pkg/inst/doc/Makefile, /pkg/inst/doc/RProtoBuf-unitTests.R[DEL], /pkg/inst/doc/RProtoBuf-unitTests.Rnw, /pkg/inst/doc/unitTests, /pkg/inst/doc/unitTests/RProtoBuf-unitTests.R: minor cleanups for the unit test vignette (same as in Rcpp) 2010-01-23 Romain Francois * [r268] /pkg/inst/doc/Makefile, /pkg/inst/doc/RProtoBuf-unitTests.R, /pkg/inst/doc/RProtoBuf-unitTests.Rnw, /pkg/inst/doc/RProtoBuf-unitTests.Rnw.brew[DEL]: borrow simpler unit test vignette from Rcpp 2010-01-11 Romain Francois * [r267] /pkg/DESCRIPTION, /pkg/src/DescriptorPoolLookup.cpp, /pkg/src/rprotobuf.h: adapt to Rcpp::wrap 2009-12-29 Romain Francois * [r266] /pkg/DESCRIPTION, /pkg/inst/unitTests/runit.golden.message.R, /pkg/src/DescriptorPoolLookup.cpp: adapt to recent changes in Rcpp 2009-12-27 Romain Francois * [r265] /pkg/inst/unitTests/data/unittest.proto, /pkg/inst/unitTests/runit.golden.message.R, /pkg/src/constructors.cpp, /pkg/src/lookup.cpp: enum might not have containing types, which used to bomb new_RS4_EnumDescriptor. fixed and unit tested * [r264] /pkg/inst/doc, /pkg/inst/doc/Makefile, /pkg/inst/doc/RProtoBuf-unitTests.Rnw.brew: a bug in .tearDown prevented the unit tests from working properly 2009-12-26 Romain Francois * [r263] /pkg/inst/doc/Makefile, /pkg/inst/doc/RProtoBuf-unitTests.Rnw.brew, /pkg/inst/doc/RProtoBuf.Rnw, /pkg/inst/unitTests/runit.golden.message.R[CPY], /pkg/inst/unitTests/runit.golden_message.R[DEL]: force cleaning pdfs before vignette creation * [r262] /pkg/src/lookup.cpp: not sorting manually anymore since std::set does it for free * [r261] /pkg/inst/unitTests/runit.draft.R[DEL], /pkg/inst/unitTests/runit.error.R[DEL], /pkg/inst/unitTests/runit.golden_message.R: started adding some proper tests * [r260] /pkg/DESCRIPTION, /pkg/src/DescriptorPoolLookup.cpp: using Rcpp >= 0.7.0.2 * [r259] /pkg/R/internals.R, /pkg/inst/unitTests/data/unittest.proto, /pkg/src/DescriptorPoolLookup.cpp, /pkg/src/DescriptorPoolLookup.h, /pkg/src/RSourceTree.cpp, /pkg/src/RSourceTree.h, /pkg/src/RWarningErrorCollector.cpp, /pkg/src/rprotobuf.cpp, /pkg/src/rprotobuf.h: fixed importing and use set in DescriptorPoolLookup * [r258] /pkg/inst/doc/Makefile, /pkg/inst/unitTests/data, /pkg/inst/unitTests/data/unittest.proto, /pkg/inst/unitTests/data/unittest_import.proto: added utils as default package in vignette makefile 2009-12-26 Dirk Eddelbuettel * [r257] /pkg/tests/doRUnit.R: wd var no longer needed either 2009-12-26 Romain Francois * [r256] /pkg/DESCRIPTION, /pkg/NAMESPACE, /pkg/cleanup, /pkg/inst/doc/Makefile, /pkg/inst/doc/RProtoBuf-unitTests.Rnw[DEL], /pkg/inst/doc/RProtoBuf-unitTests.Rnw.brew, /pkg/inst/unitTests/runTests.R, /pkg/inst/unitTests/runit.draft.R, /pkg/inst/unitTests/runit.error.R, /pkg/tests/doRUnit.R: revised display of information in unit test vignette * [r255] /pkg/NAMESPACE, /pkg/R/unit_tests.R, /pkg/inst/doc/RProtoBuf-unitTests.Rnw, /pkg/inst/unitTests, /pkg/inst/unitTests/runTests.R, /pkg/inst/unitTests/runit.draft.R, /pkg/tests, /pkg/tests/doRUnit.R: prepare for unit testing * [r254] /pkg/DESCRIPTION, /pkg/src/as.cpp, /pkg/src/rprotobuf.h: remove the external_pointer experiment (now in package CPP) 2009-12-24 Dirk Eddelbuettel * [r253] /pkg/src/ConnectionCopyingOutputStream.cpp, /pkg/src/ConnectionInputStream.cpp, /pkg/src/ConnectionOutputStream.cpp, /pkg/src/as.cpp, /pkg/src/rprotobuf.cpp: as.cpp: comment out unused rcpp namespace to fix odd "does not build on amd64" issue found by Saptarshi other files: minimal tweaks to shut 'g++ -Wall' up 2009-12-22 Romain Francois * [r252] /pkg/src/rprotobuf.h: .3 2009-12-20 Romain Francois * [r251] /pkg/DESCRIPTION, /pkg/inst/doc/RProtoBuf.Rnw, /pkg/src/DescriptorPoolLookup.cpp, /pkg/src/as.cpp, /pkg/src/rprotobuf.h: start to use Rcpp 0.7.0 features 2009-12-19 Romain Francois * [r250] /pkg/R/00classes.R, /pkg/R/completion.R, /pkg/src/rprotobuf.h: more completion for streams, and removed debugging messages which resulted in vignette crashing 2009-12-18 Romain Francois * [r249] /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/R/wrapper_CodedOutputStream.R, /pkg/man/ZeroCopyOutputStream-class.Rd, /pkg/src/rprotobuf.h, /pkg/src/streams.cpp: added methods for ZeroCopyOutputStream (actually using CodedOutputStream) 2009-12-17 Romain Francois * [r248] /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/R/completion.R, /pkg/R/wrapper_CodedInputStream.R, /pkg/R/wrapper_CodedOutputStream.R, /pkg/man/ZeroCopyOutputStream-class.Rd, /pkg/man/completion.Rd, /pkg/src/streams.cpp: +WriteRaw.ZeroCopyOutoutStream and added completion for ZeroCopy{In,Out}outStream * [r247] /pkg/NAMESPACE, /pkg/R/wrapper_CodedInputStream.R, /pkg/man/ZeroCopyInputStream-class.Rd, /pkg/src/rprotobuf.h, /pkg/src/streams.cpp: +ReadVarint64 2009-12-16 Romain Francois * [r246] /pkg/NAMESPACE, /pkg/R/wrapper_CodedInputStream.R, /pkg/man/ZeroCopyInputStream-class.Rd, /pkg/src/rprotobuf.h, /pkg/src/streams.cpp: +ReadLittleEndian{32,64} * [r245] /pkg/NAMESPACE, /pkg/R/wrapper_CodedInputStream.R, /pkg/man/ZeroCopyInputStream-class.Rd, /pkg/src/rprotobuf.h, /pkg/src/streams.cpp: +ReadVarint32 * [r244] /pkg/NAMESPACE, /pkg/R/wrapper_CodedInputStream.R, /pkg/man/ZeroCopyInputStream-class.Rd, /pkg/src/rprotobuf.h, /pkg/src/streams.cpp: +ReadString * [r243] /pkg/src/rprotobuf.h: passing R CMD check again. solved problem related to finalization of Message* * [r242] /pkg/inst/doc/RProtoBuf-unitTests.Rnw[DEL]: * [r241] /pkg/inst/doc/RProtoBuf-unitTests.Rnw: * [r240] /pkg/R/wrapper_CodedInputStream.R, /pkg/man/ArrayInputStream-class.Rd, /pkg/src/extractors.cpp, /pkg/src/rprotobuf.cpp, /pkg/src/rprotobuf.h, /pkg/src/set.cpp, /pkg/src/streams.cpp: passing R CMD check again. solved problem related to finalization of Message* * [r239] /pkg/src/constructors.cpp, /pkg/src/rprotobuf.cpp, /pkg/src/rprotobuf.h: finalizer for messages * [r238] /pkg/src/rprotobuf.h, /pkg/src/streams.cpp: also use ZeroCopyOutputStreamWrapper * [r237] /pkg/R/wrapper_CodedInputStream.R, /pkg/src/rprotobuf.h, /pkg/src/streams.cpp: using ZeroCopyInputStreamWrapper * [r236] /pkg/src/ZeroCopyOutputStreamWrapper.cpp, /pkg/src/ZeroCopyOutputStreamWrapper.h: + ZeroCopyOutputStreamWrapper C++ class * [r235] /pkg/src/ZeroCopyInputStreamWrapper.cpp, /pkg/src/ZeroCopyInputStreamWrapper.h, /pkg/src/streams.cpp: added ZeroCopyInputStreamWrapper that wraps together a zcis and a cis, so that there is no need to create a cis each time 2009-12-15 Romain Francois * [r234] /pkg/NAMESPACE, /pkg/man/ZeroCopyInputStream-class.Rd, /pkg/src/rprotobuf.h, /pkg/src/streams.cpp: added ReadRaw.ZeroCopyInputSytream * [r233] /pkg/src/ConnectionCopyingInputStream.cpp, /pkg/src/ConnectionCopyingInputStream.h, /pkg/src/ConnectionCopyingOutputStream.cpp, /pkg/src/ConnectionCopyingOutputStream.h, /pkg/src/ConnectionInputStream.cpp, /pkg/src/ConnectionInputStream.h, /pkg/src/ConnectionOutputStream.cpp, /pkg/src/ConnectionOutputStream.h, /pkg/src/read.cpp, /pkg/src/streams.cpp: rework Connection{In,Out}putStream * [r232] /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/R/wrapper_ZeroCopyInputStream.R, /pkg/man/ConnectionInputStream-class.Rd, /pkg/man/ConnectionInputStream-methods.Rd, /pkg/man/ConnectionOutputStream-class.Rd, /pkg/man/ConnectionOutputStream-methods.Rd, /pkg/src/ConnectionInputStream.cpp, /pkg/src/ConnectionInputStream.h, /pkg/src/rprotobuf.h, /pkg/src/streams.cpp: added (R side of and not yet functional, but hey) Connection{In,Out}putStream classes and methods 2009-12-14 Romain Francois * [r231] /pkg/man/Descriptor-class.Rd[CPY], /pkg/man/EnumDescriptor-class.Rd[CPY], /pkg/man/EnumValueDescriptor-class.Rd[CPY], /pkg/man/FieldDescriptor-class.Rd[CPY], /pkg/man/FileDescriptor-class.Rd[CPY], /pkg/man/Message-class.Rd[CPY], /pkg/man/MethodDescriptor-class.Rd[CPY], /pkg/man/ServiceDescriptor-class.Rd[CPY], /pkg/man/protobufDescriptor-class.Rd[DEL], /pkg/man/protobufEnumDescriptor-class.Rd[DEL], /pkg/man/protobufEnumValueDescriptor-class.Rd[DEL], /pkg/man/protobufFieldDescriptor-class.Rd[DEL], /pkg/man/protobufFileDescriptor-class.Rd[DEL], /pkg/man/protobufMessage-class.Rd[DEL], /pkg/man/protobufMethodDescriptor-class.Rd[DEL], /pkg/man/protobufServiceDescriptor-class.Rd[DEL]: remove the 'protobuf' prefix of Rd file names * [r230] /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/R/wrapper_ZeroCopyInputStream.R, /pkg/man/FileInputStream-class.Rd, /pkg/man/FileInputStream-methods.Rd, /pkg/man/FileOutputStream-class.Rd, /pkg/man/FileOutputStream-methods.Rd, /pkg/man/GetErrno-methods.Rd, /pkg/man/SetCloseOnDelete-methods.Rd, /pkg/src/rprotobuf.h, /pkg/src/streams.cpp: +File{In,Out}putStream classes and methods * [r229] /pkg/NAMESPACE, /pkg/R/wrapper_ZeroCopyInputStream.R, /pkg/man/ArrayOutputStream-class.Rd, /pkg/man/ArrayOutputStream-methods.Rd, /pkg/src/rprotobuf.h, /pkg/src/streams.cpp: +ArrayOutputStream class and constructor method 2009-12-12 Romain Francois * [r228] /pkg/R/wrapper_ZeroCopyInputStream.R: added some invisible's * [r227] /pkg/R/00classes.R, /pkg/R/wrapper_ZeroCopyInputStream.R, /pkg/man/ArrayInputStream-class.Rd, /pkg/man/ArrayInputStream-methods.Rd, /pkg/src/rprotobuf.h, /pkg/src/streams.cpp: allow block size for ArrayInputStream * [r226] /java/src/org/rproject/rprotobuf/ProtobufHttpServer.java, /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/R/wrapper_ZeroCopyInputStream.R, /pkg/man/ArrayInputStream-class.Rd, /pkg/man/ArrayInputStream-methods.Rd, /pkg/man/ZeroCopyInputStream-class.Rd, /pkg/man/ZeroCopyOutputStream-class.Rd, /pkg/src/rprotobuf.h, /pkg/src/streams.cpp: +ArrayInputStream class 2009-12-11 Romain Francois * [r225] /pkg/R/00classes.R, /pkg/R/wrapper_ZeroCopyInputStream.R, /pkg/man/ZeroCopyInputStream-class.Rd, /pkg/man/ZeroCopyOutputStream-class.Rd, /pkg/src/rprotobuf.h, /pkg/src/streams.cpp: +ZeroCopyOutputStream S4 class * [r224] /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/R/wrapper_ZeroCopyInputStream.R, /pkg/man/BackUp-methods.Rd, /pkg/man/ByteCount-methods.Rd, /pkg/man/Next-methods.Rd, /pkg/man/Skip-methods.Rd, /pkg/man/ZeroCopyInputStream-class.Rd, /pkg/src/mutators.cpp, /pkg/src/rpc_over_http.cpp, /pkg/src/rprotobuf.h, /pkg/src/streams.cpp: +ZeroCopyInputStream S4 class * [r223] /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/man/CodedInputStream-class.Rd[DEL], /pkg/src/CodedInputStream_wrapper.cpp[DEL], /pkg/src/constructors.cpp, /pkg/src/rprotobuf.h: changed my mind, don't want to expose CodedInputStream (yet) * [r222] /pkg/src/CodedInputStream_wrapper.cpp, /pkg/src/constructors.cpp, /pkg/src/rprotobuf.h: added constructor and finalizer for CodedInputStream * [r221] /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/R/rpc.R, /pkg/man/CodedInputStream-class.Rd, /pkg/man/RpcHTTP-class.Rd, /pkg/src/SocketCopyingInputStream.cpp, /pkg/src/rpc_over_http.cpp, /pkg/src/rprotobuf.h: added RpcHTTP@root slot, and CodedInputStream class 2009-12-10 Romain Francois * [r220] /pkg/inst/proto/helloworld.proto, /pkg/src/DescriptorPoolLookup.cpp, /pkg/src/DescriptorPoolLookup.h, /pkg/src/lookup.cpp, /pkg/src/methods.cpp, /pkg/src/read.cpp, /pkg/src/rpc_over_http.cpp, /pkg/src/rprotobuf.cpp, /pkg/src/rprotobuf.h: now using runtime descriptors correctly * [r219] /java/build.xml, /java/proto/helloworld.proto, /java/src/org/rproject/rprotobuf/HelloWorldInvoker.java, /java/src/org/rproject/rprotobuf/ProtobufHandler.java, /java/src/org/rproject/rprotobuf/ProtobufMethodInvoker.java, /java/src/org/rproject/rprotobuf/ProtobufMethodPool.java: added hello world example * [r218] /java/src/org/rproject/rprotobuf/EchoInvoker.java, /java/src/org/rproject/rprotobuf/MethodImplementation.java, /java/src/org/rproject/rprotobuf/ProtobufMethodPool.java: added annotation (not used yet) * [r217] /java/build.xml, /java/proto, /java/proto/addressbook.proto, /java/src/org/rproject/rprotobuf/EchoInvoker.java, /java/src/org/rproject/rprotobuf/ProtobufMethodInvoker.java, /java/src/org/rproject/rprotobuf/ProtobufMethodPool.java: more generic java code 2009-12-09 Romain Francois * [r216] /java/start.sh: added convenience start script for the java server * [r215] /java/src/org/rproject/rprotobuf/ProtobufMethodPool.java: more flexible java server code * [r214] /java/README, /java/build.xml, /java/lib, /java/lib/protobuf-java-2.2.0.jar, /java/src/org/rproject/rprotobuf/EchoInvoker.java, /java/src/org/rproject/rprotobuf/ProtobufHandler.java, /java/src/org/rproject/rprotobuf/ProtobufMethodInvoker.java, /java/src/org/rproject/rprotobuf/ProtobufMethodPool.java, /pkg/inst/proto/addressbook.proto: more flexible java server code * [r213] /java/README, /java/src/org/rproject/rprotobuf/ProtobufHandler.java, /java/src/org/rproject/rprotobuf/ProtobufHttpServer.java, /java/src/org/rproject/rprotobuf/ProtobufMethodInvoker.java, /java/src/org/rproject/rprotobuf/ProtobufMethodPool.java, /pkg/src/rpc_over_http.cpp: functional rpc over http R client and java server 2009-12-08 Romain Francois * [r212] /pkg/src/channel.cpp[DEL], /pkg/src/rpc_over_http.cpp, /pkg/src/rprotobuf.h: started to work on rpc over http * [r211] /java, /java/build.properties, /java/build.xml, /java/src, /java/src/org, /java/src/org/rproject, /java/src/org/rproject/rprotobuf, /java/src/org/rproject/rprotobuf/ProtobufHttpServer.java: added dummy java rpc over http server * [r210] /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/R/rpc.R, /pkg/man/RpcHTTP-class.Rd, /pkg/man/invokeLocally.Rd: added invoke, removed invokeLocally, added RpcHTTP class to represent the rpc over http protocol 2009-12-08 Dirk Eddelbuettel * [r209] /pkg/R/listPeople.R, /pkg/src/clear_person_R.cpp, /pkg/src/list_people_R.cpp: minor robustification against empty addressbook file 2009-12-06 Dirk Eddelbuettel * [r208] /pkg/NAMESPACE, /pkg/R/addPerson.R, /pkg/man/addPerson.Rd, /pkg/src/clear_person_R.cpp: added clearPerson() support with kudos to Romain as usual :) 2009-12-06 Romain Francois * [r207] /pkg/inst/proto/protobufrpc.proto[DEL]: not using protobuf-rpc anymore * [r206] /pkg/src/DescriptorPoolLookup.cpp, /pkg/src/EnumDescriptor_wrapper.cpp, /pkg/src/FieldDescriptor_wrapper.cpp, /pkg/src/Makevars.in, /pkg/src/RSourceTree.cpp, /pkg/src/RSourceTree.h, /pkg/src/RWarningErrorCollector.cpp, /pkg/src/RWarningErrorCollector.h, /pkg/src/RconnectionCopyingInputStream.h, /pkg/src/ServiceDescriptor_wrapper.cpp, /pkg/src/SocketCopyingInputStream.h, /pkg/src/add.cpp, /pkg/src/as.cpp, /pkg/src/ascharacter.cpp, /pkg/src/aslist.cpp, /pkg/src/channel.cpp, /pkg/src/clear.cpp, /pkg/src/clone.cpp, /pkg/src/completion.cpp, /pkg/src/constructors.cpp, /pkg/src/containing_type.cpp, /pkg/src/extractors.cpp, /pkg/src/field_count.cpp, /pkg/src/fileDescriptor.cpp, /pkg/src/has.cpp, /pkg/src/identical.cpp, /pkg/src/initialized.cpp, /pkg/src/length.cpp, /pkg/src/lookup.cpp, /pkg/src/merge.cpp, /pkg/src/methods.cpp, /pkg/src/mutators.cpp, /pkg/src/name.cpp, /pkg/src/read.cpp, /pkg/src/rprotobuf.cpp, /pkg/src/rprotobuf.h, /pkg/src/serialize.cpp, /pkg/src/set.cpp, /pkg/src/size.cpp, /pkg/src/swap.cpp: not using using * [r205] /pkg/src/RTcpChannel.cpp[DEL]: removing * [r204] /pkg/src/RTcpChannel.h[DEL]: removing * [r203] /pkg/src/RTcpChannel.cpp: ùù * [r202] /pkg/src/RTcpChannel.h: ùù * [r201] /pkg/DESCRIPTION, /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/R/EnumDescriptor_wrapper.R, /pkg/R/EnumValueDescriptor_wrapper.R, /pkg/R/FieldDescriptor_wrapper.R, /pkg/R/MethodDescriptor_wrapper.R, /pkg/R/ServiceDescriptor_wrapper.R, /pkg/R/add.R, /pkg/R/aslist.R, /pkg/R/clear.R, /pkg/R/clone.R, /pkg/R/completion.R, /pkg/R/containing_type.R, /pkg/R/debug_string.R, /pkg/R/descriptor.R, /pkg/R/exceptions.R, /pkg/R/field_count.R, /pkg/R/has.R, /pkg/R/identical.R, /pkg/R/initialized.R, /pkg/R/merge.R, /pkg/R/read.R, /pkg/R/rpc.R, /pkg/R/serialize.R, /pkg/R/set.R, /pkg/R/size.R, /pkg/R/swap.R, /pkg/R/with.R, /pkg/inst/doc/RProtoBuf.Rnw, /pkg/man/P.Rd, /pkg/man/RProtoBuf-package.Rd, /pkg/man/add.Rd, /pkg/man/asMessage.Rd, /pkg/man/aslist.Rd, /pkg/man/bytesize.Rd, /pkg/man/clear.Rd, /pkg/man/clone.Rd, /pkg/man/completion.Rd, /pkg/man/containing_type-methods.Rd, /pkg/man/descriptor.Rd, /pkg/man/enum_type.Rd, /pkg/man/enum_type_count.Rd, /pkg/man/fetch.Rd, /pkg/man/field.Rd, /pkg/man/field_count.Rd, /pkg/man/fileDescriptor.Rd, /pkg/man/has.Rd, /pkg/man/invokeLocally.Rd, /pkg/man/isInitialized.Rd, /pkg/man/is_extension.Rd, /pkg/man/label.Rd, /pkg/man/merge.Rd, /pkg/man/name.Rd, /pkg/man/nested_type.Rd, /pkg/man/nested_type_count.Rd, /pkg/man/number.Rd, /pkg/man/protobufDescriptor-class.Rd, /pkg/man/protobufEnumDescriptor-class.Rd, /pkg/man/protobufEnumValueDescriptor-class.Rd, /pkg/man/protobufFieldDescriptor-class.Rd, /pkg/man/protobufFileDescriptor-class.Rd, /pkg/man/protobufMessage-class.Rd, /pkg/man/protobufMethodDescriptor-class.Rd, /pkg/man/protobufServiceDescriptor-class.Rd, /pkg/man/read.Rd, /pkg/man/set.Rd, /pkg/man/size.Rd, /pkg/man/sizegets.Rd, /pkg/man/swap.Rd, /pkg/man/type.Rd, /pkg/man/with.Rd, /pkg/src/add.cpp, /pkg/src/constructors.cpp, /pkg/src/extractors.cpp, /pkg/src/lookup.cpp, /pkg/src/merge.cpp, /pkg/src/mutators.cpp, /pkg/src/read.cpp, /pkg/src/rprotobuf.cpp: removing the protobuf prefix of the S4 classes 2009-12-05 Romain Francois * [r200] /pkg/NAMESPACE, /pkg/R/MethodDescriptor_wrapper.R, /pkg/R/completion.R, /pkg/R/rpc.R, /pkg/man/protobufMethodDescriptor-class.Rd: + {in,out}put_type.MethodDescriptor * [r199] /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/R/ServiceDescriptor_wrapper.R, /pkg/R/completion.R, /pkg/man/protobufServiceDescriptor-class.Rd: + method.ServiceDescriptor * [r198] /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/R/EnumValueDescriptor_wrapper.R, /pkg/R/ServiceDescriptor_wrapper.R, /pkg/man/protobufServiceDescriptor-class.Rd, /pkg/src/ServiceDescriptor_wrapper.cpp, /pkg/src/rprotobuf.h: added some methods for ServiceDescriptor * [r197] /pkg/R/EnumDescriptor_wrapper.R, /pkg/man/protobufEnumValueDescriptor-class.Rd: added EnumValueDescriptor class * [r196] /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/R/EnumDescriptor_wrapper.R, /pkg/R/FieldDescriptor_wrapper.R, /pkg/R/completion.R, /pkg/R/debug_string.R, /pkg/R/field_count.R, /pkg/man/protobufDescriptor-class.Rd, /pkg/man/protobufEnumDescriptor-class.Rd, /pkg/man/protobufEnumValueDescriptor-class.Rd, /pkg/man/protobufFieldDescriptor-class.Rd, /pkg/src/EnumDescriptor_wrapper.cpp, /pkg/src/as.cpp, /pkg/src/ascharacter.cpp, /pkg/src/constructors.cpp, /pkg/src/rprotobuf.h: added EnumValueDescriptor class 2009-12-05 Dirk Eddelbuettel * [r195] /pkg/inst/doc/RProtoBuf.Rnw: added some stuff near the beginning about 'static' use which motivates the dynamic use nicely some spit and polish for intro as well 2009-12-04 Romain Francois * [r194] /pkg/R/00classes.R, /pkg/man/protobufEnumDescriptor-class.Rd, /pkg/src/EnumDescriptor_wrapper.cpp, /pkg/src/rprotobuf.h: +length.protobufEnumDescriptor * [r193] /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/R/FieldDescriptor_wrapper.R, /pkg/R/completion.R, /pkg/man/protobufFieldDescriptor-class.Rd, /pkg/src/FieldDescriptor_wrapper.cpp, /pkg/src/rprotobuf.h: +{message,enum}_type.FieldDescriptor * [r192] /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/R/FieldDescriptor_wrapper.R, /pkg/man/protobufFieldDescriptor-class.Rd, /pkg/src/FieldDescriptor_wrapper.cpp, /pkg/src/rprotobuf.h: + {has_default_value,default_value}.FieldDescriptor~ * [r191] /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/R/FieldDescriptor_wrapper.R, /pkg/R/completion.R, /pkg/man/label.Rd, /pkg/man/protobufFieldDescriptor-class.Rd, /pkg/src/FieldDescriptor_wrapper.cpp, /pkg/src/rprotobuf.h: +{label,is_repeated,is_required,is_optional}.FieldDescriptor * [r190] /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/R/FieldDescriptor_wrapper.R, /pkg/R/completion.R, /pkg/man/protobufFieldDescriptor-class.Rd, /pkg/man/type.Rd, /pkg/src/FieldDescriptor_wrapper.cpp, /pkg/src/rprotobuf.h: +{type.cpp_type}.FieldDescriptor * [r189] /pkg/src/FieldDescriptor_wrapper.cpp, /pkg/src/rprotobuf.h: +number.FieldDescriptor * [r188] /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/R/FieldDescriptor_wrapper.R, /pkg/R/completion.R, /pkg/man/number.Rd, /pkg/man/protobufFieldDescriptor-class.Rd: +number.FieldDescriptor * [r187] /pkg/TODO: updated TODO * [r186] /pkg/R/field_count.R: minor fix * [r185] /pkg/NAMESPACE, /pkg/R/FieldDescriptor_wrapper.R, /pkg/R/field_count.R, /pkg/man/is_extension.Rd, /pkg/man/protobufFieldDescriptor-class.Rd, /pkg/src/FieldDescriptor_wrapper.cpp, /pkg/src/rprotobuf.h: + is_extension.FieldDescriptor * [r184] /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/R/completion.R, /pkg/R/field_count.R, /pkg/man/enum_type.Rd, /pkg/man/protobufDescriptor-class.Rd, /pkg/src/field_count.cpp, /pkg/src/rprotobuf.h: + enum_type.Descriptor method 2009-12-03 Romain Francois * [r183] /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/R/completion.R, /pkg/R/field_count.R, /pkg/man/nested_type.Rd, /pkg/man/protobufDescriptor-class.Rd, /pkg/src/field_count.cpp, /pkg/src/rprotobuf.h: +nested_type.Descriptor method * [r182] /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/R/completion.R, /pkg/R/field_count.R, /pkg/man/enum_type_count.Rd, /pkg/man/field.Rd, /pkg/man/protobufDescriptor-class.Rd, /pkg/src/field_count.cpp, /pkg/src/rprotobuf.h: added field.Descriptor method * [r181] /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/R/completion.R, /pkg/R/field_count.R, /pkg/man/nested_type_count.Rd, /pkg/man/protobufDescriptor-class.Rd, /pkg/src/field_count.cpp, /pkg/src/rprotobuf.h: nested_type_count.protobufDescriptor * [r180] /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/R/completion.R, /pkg/R/field_count.R, /pkg/man/field_count.Rd, /pkg/man/protobufDescriptor-class.Rd, /pkg/src/field_count.cpp, /pkg/src/rprotobuf.h: + field_count.protobufDescriptor method * [r179] /pkg/DESCRIPTION: added BugReports description field * [r178] /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/R/completion.R, /pkg/R/containing_type.R, /pkg/man/containing_type-methods.Rd, /pkg/man/protobufDescriptor-class.Rd, /pkg/man/protobufEnumDescriptor-class.Rd, /pkg/man/protobufFieldDescriptor-class.Rd, /pkg/src/containing_type.cpp, /pkg/src/rprotobuf.h: added containing_type.protobuf{Descriptor,FieldDescriptor,EnumDescriptor} 2009-12-03 Dirk Eddelbuettel * [r177] /pkg/NAMESPACE, /pkg/R/addPerson.R, /pkg/man/addPerson.Rd, /pkg/man/listPeople.Rd, /pkg/src/add_person_R.cpp: added simple addPerson() R function, manual page and C++ implementation 2009-12-02 Romain Francois * [r176] /pkg/src/initialized.cpp: isInitialized gains the names of the fields that are not initialized * [r175] /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/inst/doc/RProtoBuf.Rnw, /pkg/man/asMessage.Rd, /pkg/src/as.cpp, /pkg/src/rprotobuf.h: added asMessage function * [r174] /pkg/NAMESPACE, /pkg/man/throw.Rd[DEL], /pkg/src/exceptions.cpp: throw not exported anymore * [r173] /pkg/man/protobufFileDescriptor-class.Rd: added name.protobufFileDescriptor * [r172] /pkg/R/00classes.R, /pkg/R/completion.R, /pkg/src/name.cpp, /pkg/src/rprotobuf.h: added more fileDescriptor methods * [r171] /pkg/R/00classes.R, /pkg/R/completion.R, /pkg/R/descriptor.R, /pkg/R/rpc.R, /pkg/man/fileDescriptor.Rd, /pkg/src/fileDescriptor.cpp, /pkg/src/rprotobuf.h: added more fileDescriptor methods * [r170] /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/R/aslist.R, /pkg/man/aslist.Rd, /pkg/man/protobufServiceDescriptor-class.Rd, /pkg/src/aslist.cpp, /pkg/src/completion.cpp, /pkg/src/rprotobuf.h: added as.list.protobufServiceDescriptor * [r169] /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/R/completion.R, /pkg/R/rpc.R, /pkg/man/completion.Rd, /pkg/man/protobufServiceDescriptor-class.Rd, /pkg/src/extractors.cpp, /pkg/src/rprotobuf.h: misc * [r168] /pkg/R/00classes.R, /pkg/man/name.Rd, /pkg/src/name.cpp, /pkg/src/rprotobuf.h: more name methods * [r167] /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/R/completion.R, /pkg/inst/doc/RProtoBuf.Rnw, /pkg/man/name.Rd, /pkg/man/protobufServiceDescriptor-class.Rd, /pkg/src/name.cpp, /pkg/src/rprotobuf.h: added name method and implementations for Decriptor and FieldDescriptor 2009-12-01 Romain Francois * [r166] /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/R/aslist.R, /pkg/R/completion.R, /pkg/man/aslist.Rd, /pkg/man/completion.Rd, /pkg/man/protobufFileDescriptor-class.Rd, /pkg/src/aslist.cpp, /pkg/src/completion.cpp, /pkg/src/rprotobuf.h: added as.list.protobufFileDescriptor * [r165] /pkg/R/debug_string.R, /pkg/src/ascharacter.cpp, /pkg/src/rprotobuf.h: completion, toString, as.character for protobufFileDescriptor * [r164] /pkg/R/00classes.R, /pkg/R/completion.R, /pkg/man/completion.Rd, /pkg/man/protobufFileDescriptor-class.Rd: completion, toString, as.character for protobufFileDescriptor * [r163] /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/R/completion.R, /pkg/R/descriptor.R, /pkg/R/rpc.R, /pkg/inst/doc/RProtoBuf.Rnw, /pkg/man/fileDescriptor.Rd, /pkg/man/protobufFileDescriptor-class.Rd, /pkg/src/constructors.cpp, /pkg/src/fileDescriptor.cpp, /pkg/src/rprotobuf.h: added protobufFileDescriptor S4 class + fileDescriptor method 2009-11-30 Romain Francois * [r162] /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/R/rpc.R, /pkg/src/RTcpChannel.cpp, /pkg/src/RTcpChannel.h, /pkg/src/SocketCopyingInputStream.cpp, /pkg/src/SocketCopyingInputStream.h, /pkg/src/channel.cpp, /pkg/src/rprotobuf.h: playing with sockets 2009-11-23 Romain Francois * [r161] /www/index.php: update the page 2009-11-22 Romain Francois * [r160] /pkg/src/RTcpChannel.cpp, /pkg/src/RTcpChannel.h: * [r159] /pkg/src/sisocks.h: added sisocks.h header from Rserve * [r158] /pkg/src/Makevars.in, /pkg/src/RTcpChannel.cpp, /pkg/src/RTcpChannel.h: slowly putting things in place for rpc (inspired from the protobuf-rpc project) * [r157] /pkg/src/serialize.cpp: discovered the SerializeToArray method, simplify code * [r156] /pkg/src/mutators.cpp, /pkg/src/rprotobuf.h, /pkg/src/serialize.cpp: allow messages as input of string and bytes fields * [r155] /pkg/inst/proto/protobufrpc.proto, /pkg/src: added proto file from protobufrpc project * [r154] /pkg/R/set.R, /pkg/src/Makevars.in, /pkg/src/mutators.cpp: allow raw vector as input of string or bytes fields 2009-11-21 Romain Francois * [r153] /www/index.php: start to make the project page * [r152] /pkg/DESCRIPTION: suggesting svUnit (unit tests) * [r151] /pkg/inst/doc, /pkg/inst/doc/RProtoBuf-unitTests.Rnw: added (empty) unit test vignette * [r150] /pkg/inst/doc/RProtoBuf.Rnw: update the main vignette to show reading from payload * [r149] /pkg/R/read.R, /pkg/R/serialize.R, /pkg/man/read.Rd, /pkg/src/read.cpp, /pkg/src/rprotobuf.h: reading messages from raw vector (payload) * [r148] /pkg/NEWS, /pkg/R/read.R: open the connection at start on read 2009-11-18 Romain Francois * [r147] /pkg/inst/proto/addressbook.proto: for the quickref vignette in one page 2009-11-18 Dirk Eddelbuettel * [r146] /pkg/cleanup: also remove temp files for quickref vignette 2009-11-17 Romain Francois * [r145] /pkg/src/mutators.cpp, /pkg/src/size.cpp, /pkg/src/swap.cpp: removed the conditional compiling for protobuf 2.1 * [r144] /pkg/man/invokeLocally.Rd, /pkg/man/protobufMethodDescriptor-class.Rd, /pkg/man/protobufServiceDescriptor-class.Rd: pleasing R CMD check 2009-11-16 Dirk Eddelbuettel * [r143] /pkg/configure, /pkg/configure.in: further improvements to configure via pkg-config * [r142] /pkg/cleanup: let cleanup nuke a few LaTeX files 2009-11-16 Romain Francois * [r141] /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/R/debug_string.R, /pkg/R/rpc.R, /pkg/TODO, /pkg/inst/proto/addressbook.proto, /pkg/man/protobufMethodDescriptor-class.Rd, /pkg/man/protobufServiceDescriptor-class.Rd, /pkg/src/ascharacter.cpp, /pkg/src/constructors.cpp, /pkg/src/lookup.cpp, /pkg/src/methods.cpp, /pkg/src/read.cpp, /pkg/src/rprotobuf.cpp, /pkg/src/rprotobuf.h: starting to play with (local) rpc services 2009-11-16 Dirk Eddelbuettel * [r140] /pkg/configure: updated configure * [r139] /pkg/DESCRIPTION, /pkg/configure.in: updated configure.in to use pkg-config updated DESCRIPTON 2009-11-16 Romain Francois * [r138] /pkg/inst/doc: * [r137] /pkg/inst/doc/RProtoBuf-quickref.Rnw: added quick ref vignette * [r136] /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/R/add.R, /pkg/R/completion.R, /pkg/inst/doc/RProtoBuf.Rnw, /pkg/man/add.Rd, /pkg/src/add.cpp, /pkg/src/mutators.cpp, /pkg/src/rprotobuf.h: added add method to add values to a repeated field 2009-11-14 Romain Francois * [r135] /pkg/NAMESPACE, /pkg/R/identical.R, /pkg/inst/doc/RProtoBuf.Rnw, /pkg/man/protobufMessage-class.Rd, /pkg/src/identical.cpp, /pkg/src/rprotobuf.h: added all.equal * [r134] /pkg/DESCRIPTION, /pkg/man/RProtoBuf-package.Rd: updated DESCRIPTION and package help page * [r133] /pkg/R/identical.R, /pkg/inst/doc/RProtoBuf.Rnw, /pkg/man/protobufMessage-class.Rd: added == and != * [r132] /pkg/NAMESPACE, /pkg/R/identical.R, /pkg/inst/doc/RProtoBuf.Rnw, /pkg/man/protobufMessage-class.Rd, /pkg/src/identical.cpp, /pkg/src/rprotobuf.h: added identical method to compare two messages * [r131] /pkg/inst/doc/RProtoBuf.Rnw: some more vignette content 2009-11-13 Romain Francois * [r130] /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/R/completion.R, /pkg/R/debug_string.R, /pkg/inst/doc/RProtoBuf.Rnw, /pkg/man/protobufDescriptor-class.Rd, /pkg/man/protobufEnumDescriptor-class.Rd, /pkg/man/protobufFieldDescriptor-class.Rd, /pkg/man/protobufMessage-class.Rd: added toString as an alias to as.character * [r129] /pkg/inst/doc/RProtoBuf.Rnw: some more vignette content * [r128] /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/R/set.R, /pkg/inst/doc/RProtoBuf.Rnw, /pkg/man/fetch.Rd, /pkg/src/extractors.cpp, /pkg/src/rprotobuf.h, /pkg/src/set.cpp: added fetch method * [r127] /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/R/completion.R, /pkg/R/set.R, /pkg/inst/doc/RProtoBuf.Rnw, /pkg/man/completion.Rd, /pkg/man/set.Rd, /pkg/src/mutators.cpp, /pkg/src/rprotobuf.h: added set method 2009-11-13 Dirk Eddelbuettel * [r126] /pkg/inst/doc/RProtoBuf.Rnw: a few more updates * [r125] /pkg/inst/doc/RProtoBuf.Rnw: few small updates and tweaks * [r124] /pkg/DESCRIPTION: updated DESCRIPTION 2009-11-12 Romain Francois * [r123] /pkg/inst/doc/RProtoBuf.Rnw: some more vignette content * [r122] /pkg/R/00classes.R, /pkg/inst/doc/RProtoBuf.Rnw, /pkg/man/protobufFieldDescriptor-class.Rd, /pkg/src/rprotobuf.h: added $ for protobufFieldDescriptor (for completeness) * [r121] /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/R/completion.R, /pkg/R/descriptor.R, /pkg/inst/doc/RProtoBuf.Rnw, /pkg/man/descriptor.Rd, /pkg/src/extractors.cpp: added descriptor method * [r120] /pkg/R/internals.R, /pkg/src/rprotobuf.cpp, /pkg/src/rprotobuf.h: added (unexported) function getProtobufLibVersion * [r119] /pkg/src/mutators.cpp: use the correct version for the test #if GOOGLE_PROTOBUF_VERSION < 200200 * [r118] /pkg/src/mutators.cpp: use the correct version for the test #if GOOGLE_PROTOBUF_VERSION < 200200 * [r117] /pkg/inst/doc/RProtoBuf.Rnw: no hardcoding Sweave location * [r116] /pkg/R/00classes.R, /pkg/R/completion.R, /pkg/inst/doc/RProtoBuf.Rnw: some more vignette content 2009-11-12 Dirk Eddelbuettel * [r115] /pkg/src/mutators.cpp: make -Wall happy by commenting out one var, and providing more switch targets 2009-11-12 Romain Francois * [r114] /pkg/inst/doc/RProtoBuf.Rnw: some more vignette content * [r113] /pkg/inst/doc/RProtoBuf.Rnw, /pkg/src/size.cpp, /pkg/src/swap.cpp: correct swaping messages with 2.1 libproto * [r112] /pkg/R/00classes.R, /pkg/R/completion.R, /pkg/R/swap.R, /pkg/demo/addressbook.R, /pkg/inst/doc/RProtoBuf.Rnw: make swap use 1-based indexing * [r111] /pkg/R/00classes.R, /pkg/inst/doc/RProtoBuf.Rnw: some more content on the vignette * [r110] /pkg/src/rprotobuf.cpp: added some code to control which version of the libprotobuf we require (currently 2.1, but will be 2.2 soon) * [r109] /pkg/DESCRIPTION, /pkg/NAMESPACE, /pkg/R/zzz.R, /pkg/src/rprotobuf.cpp, /pkg/src/rprotobuf.h: added some code to control which version of the libprotobuf we require (currently 2.1, but will be 2.2 soon) * [r108] /pkg/inst/doc, /pkg/inst/doc/RProtoBuf.Rnw, /pkg/src/mutators.cpp, /pkg/src/size.cpp, /pkg/src/swap.cpp: added some conditional compiling to make it work with libprotobuf < 2.2 2009-11-11 Romain Francois * [r107] /pkg/inst/doc/RProtoBuf.Rnw, /pkg/inst/proto/addressbook.proto: some more content for the vignette * [r106] /pkg/inst/doc/RProtoBuf.tex[DEL]: removed tex file * [r105] /pkg/inst/doc, /pkg/inst/doc/RProtoBuf.Rnw, /pkg/inst/doc/RProtoBuf.tex, /pkg/inst/proto/addressbook.proto: started vignette * [r104] /pkg/DESCRIPTION: Rcpp >= 0.6.8 2009-11-10 Romain Francois * [r103] /pkg/R/swap.R, /pkg/demo/addressbook.R: some more code in demo * [r102] /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/R/completion.R, /pkg/R/swap.R, /pkg/man/swap.Rd, /pkg/src/clear.cpp, /pkg/src/rprotobuf.h, /pkg/src/swap.cpp: added swap * [r101] /pkg/R/00classes.R, /pkg/R/clear.R, /pkg/R/completion.R, /pkg/man/clear.Rd, /pkg/src/clear.cpp, /pkg/src/rprotobuf.h, /pkg/src/size.cpp: added field argument to clear * [r100] /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/R/size.R, /pkg/man/size.Rd, /pkg/man/sizegets.Rd, /pkg/src/rprotobuf.h, /pkg/src/size.cpp: + size<- * [r99] /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/R/size.R, /pkg/man/size.Rd, /pkg/src/mutators.cpp, /pkg/src/rprotobuf.cpp, /pkg/src/rprotobuf.h, /pkg/src/size.cpp: added size method * [r98] /pkg/src/mutators.cpp: minot tweaks * [r97] /pkg/src/mutators.cpp: fail mutation before resizing * [r96] /pkg/src/mutators.cpp, /pkg/src/rprotobuf.h: nicer and more efficient mutator code (discovered Reflection->RemoveLast method) * [r95] /pkg/R/00classes.R: using a switch in $ * [r94] /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/R/clear.R, /pkg/man/clear.Rd, /pkg/src/aslist.cpp, /pkg/src/clear.cpp, /pkg/src/mutators.cpp, /pkg/src/rprotobuf.h: added clear method * [r93] /pkg/src/RWarningErrorCollector.cpp, /pkg/src/RWarningErrorCollector.h, /pkg/src/rprotobuf.cpp: properly implement MultiFileErrorCollector to send an R warning instead of printing stuff to cout * [r92] /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/man/protobufMessage-class.Rd, /pkg/src/extractors.cpp, /pkg/src/mutators.cpp: added [[ and [[<- methods for messages using the declared tag number 2009-11-09 Romain Francois * [r91] /pkg/src/DescriptorPoolLookup.cpp, /pkg/src/DescriptorPoolLookup.h, /pkg/src/lookup.cpp, /pkg/src/rprotobuf.cpp: maintain list of currently known types in attached DescriptorPool 2009-11-09 Dirk Eddelbuettel * [r90] /pkg/src/list_people_R.cpp: remove RcppList implementation which we now get from Rcpp (>= 0.6.7) 2009-11-09 Romain Francois * [r89] /pkg/src/rprotobuf.cpp: using RSourceTree instead of DiskSourceTree * [r88] /pkg/src/RSourceTree.cpp, /pkg/src/RSourceTree.h: adding a simple SourceTree implementation * [r87] /pkg/DESCRIPTION, /pkg/man/RProtoBuf-package.Rd: required Rcpp >= 0.6.7 * [r86] /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/R/completion.R, /pkg/R/initialized.R, /pkg/man/isInitialized.Rd, /pkg/man/protobufMessage-class.Rd, /pkg/src/initialized.cpp, /pkg/src/rprotobuf.h: added isInitialized method * [r85] /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/man/protobufMessage-class.Rd, /pkg/src/length.cpp, /pkg/src/rprotobuf.h: added length method for messages * [r84] /pkg/R/internals.R: minor * [r83] /pkg/NAMESPACE, /pkg/R/size.R, /pkg/demo/io.R, /pkg/man/RProtoBuf-package.Rd, /pkg/man/bytesize.Rd, /pkg/src/rprotobuf.h, /pkg/src/size.cpp: added bytesize method * [r82] /pkg/TODO, /pkg/demo/00Index, /pkg/demo/addressbook.R, /pkg/demo/io.R, /pkg/src/RconnectionCopyingInputStream.cpp: added io demo showing how to use binary connections to read and write messages 2009-11-08 Romain Francois * [r81] /pkg/src/RconnectionCopyingInputStream.cpp: minor doc tweaks * [r80] /pkg/src/RconnectionCopyingInputStream.cpp, /pkg/src/RconnectionCopyingInputStream.h: factoring out getReadBinCall * [r79] /pkg/src/RconnectionCopyingInputStream.cpp: minor doc tweaks * [r78] /pkg/R/read.R, /pkg/src/RconnectionCopyingInputStream.cpp, /pkg/src/RconnectionCopyingInputStream.h, /pkg/src/read.cpp, /pkg/src/rprotobuf.h: reading from binary connections * [r77] /pkg/R/read.R, /pkg/R/serialize.R, /pkg/man/read.Rd, /pkg/src/read.cpp, /pkg/src/serialize.cpp: silence R CMD check 2009-11-08 Dirk Eddelbuettel * [r76] /pkg/man/protobufMessage-class.Rd: small correction to tail of example * [r75] /pkg/src/rprotobuf.h: make it work with version 2.1 of ProtoBuf 2009-11-08 Romain Francois * [r74] /pkg/man/protobufMessage-class.Rd: minor doc tweaks * [r73] /pkg/R/serialize.R, /pkg/man/protobufMessage-class.Rd: minor doc tweaks * [r72] /pkg/R/serialize.R, /pkg/src/rprotobuf.h, /pkg/src/serialize.cpp: workaround for serializing to binary connections * [r71] /pkg/R/serialize.R, /pkg/src/connections.h, /pkg/src/read.cpp, /pkg/src/rprotobuf.h, /pkg/src/serialize.cpp: use partial on serialize and parse to allow message lacking required fields 2009-11-07 Dirk Eddelbuettel * [r70] /pkg/DESCRIPTION: finally set Date svn property on this to have the Date filled in automatically 2009-11-06 Romain Francois * [r69] /pkg/R/serialize.R, /pkg/man/protobufMessage-class.Rd, /pkg/src/read.cpp, /pkg/src/rprotobuf.h, /pkg/src/serialize.cpp: serialize message to a file * [r68] /pkg/man/read.Rd: mention the read pseudi method * [r67] /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/R/completion.R, /pkg/R/read.R, /pkg/man/read.Rd, /pkg/src/read.cpp, /pkg/src/rprotobuf.cpp, /pkg/src/rprotobuf.h: reading messages from files 2009-11-05 Dirk Eddelbuettel * [r66] /pkg/src/Makevars.in: simplification in that we no longer need to list all .cpp files as dependants 2009-11-05 Romain Francois * [r65] /pkg/TODO: added services to the TODO list * [r64] /pkg/DESCRIPTION: added more urls and a MailingList field 2009-11-05 Dirk Eddelbuettel * [r63] /pkg/demo/00Index: make 'R CMD check' happy * [r62] /pkg/src/Makevars.in: adjusted Makevars.in for addressbook.proto in inst/proto/ * [r61] /pkg/inst/proto/addressbook.proto[CPY], /pkg/src/addressbook.proto[DEL]: moved addressbook.proto from src/ to inst/proto/ * [r60] /pkg/inst/examples/addressbook.proto[DEL], /pkg/inst/proto/addressbook.proto[DEL]: removed two extra addressbook.proto files 2009-11-05 Romain Francois * [r59] /pkg/NAMESPACE, /pkg/R/merge.R, /pkg/demo/00Index, /pkg/man/merge.Rd, /pkg/src/Makevars.in, /pkg/src/merge.cpp, /pkg/src/rprotobuf.h: + merge * [r58] /pkg/R/clone.R: added clone 2009-11-04 Romain Francois * [r57] /pkg/demo, /pkg/demo/addressbook.R: added demo file 2009-11-04 Dirk Eddelbuettel * [r56] /pkg/src/aslist.cpp, /pkg/src/mutators.cpp, /pkg/src/update.cpp: commented-out two unused variables and init'ed another, all to make 'g++ -Wall' 2009-11-04 Romain Francois * [r55] /pkg/TODO: added TODO * [r54] /pkg/DESCRIPTION, /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/R/aslist.R, /pkg/R/completion.R, /pkg/R/debug_string.R, /pkg/R/has.R, /pkg/R/with.R, /pkg/man/P.Rd, /pkg/man/RProtoBuf-package.Rd, /pkg/man/aslist.Rd, /pkg/man/clone.Rd, /pkg/man/completion.Rd, /pkg/man/has.Rd, /pkg/man/protobufDescriptor-class.Rd, /pkg/man/protobufEnumDescriptor-class.Rd, /pkg/man/protobufFieldDescriptor-class.Rd, /pkg/man/protobufMessage-class.Rd, /pkg/man/with.Rd, /pkg/src/Makevars.in, /pkg/src/ascharacter.cpp, /pkg/src/aslist.cpp, /pkg/src/clone.cpp, /pkg/src/completion.cpp, /pkg/src/connections.h, /pkg/src/constructors.cpp, /pkg/src/exceptions.cpp, /pkg/src/extractors.cpp, /pkg/src/has.cpp, /pkg/src/lookup.cpp, /pkg/src/mutators.cpp, /pkg/src/rprotobuf.cpp, /pkg/src/rprotobuf.h, /pkg/src/serialize.cpp, /pkg/src/update.cpp: lots of updates. fully working mutators 2009-11-02 Dirk Eddelbuettel * [r53] /pkg/src/completion.cpp, /pkg/src/constructors.cpp, /pkg/src/exceptions.cpp, /pkg/src/extractors.cpp, /pkg/src/lookup.cpp, /pkg/src/mutators.cpp, /pkg/src/rprotobuf.cpp, /pkg/src/rprotobuf.h, /pkg/src/serialize.cpp: switch from four namespace to just one * [r52] /pkg/src/extractors.cpp: add default initialisation for SEXP to keep g++ -Wall happy 2009-11-02 Romain Francois * [r51] /pkg/src/Makevars.in, /pkg/src/constructors.cpp, /pkg/src/mutators.cpp, /pkg/src/rprotobuf.cpp, /pkg/src/rprotobuf.h: minimal implementation of mutators (only non-repeated fields atm) * [r50] /pkg/R/zzz.R, /pkg/src/lookup.cpp, /pkg/src/rprotobuf.cpp, /pkg/src/rprotobuf.h: enable lookup mechanism (using full path for now) 2009-11-01 Romain Francois * [r49] /pkg/R/zzz.R: added readProtoFiles to simplify importing of proto definitions from package * [r48] /pkg/NAMESPACE, /pkg/R/internals.R, /pkg/R/zzz.R, /pkg/inst/proto, /pkg/inst/proto/addressbook.proto, /pkg/man/readProtoFiles.Rd: added readProtoFiles to simplify importing of proto definitions from packages 2009-10-31 Romain Francois * [r47] /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/man/throw.Rd: +Rd.throw * [r46] /pkg/man/protobufFieldDescriptor-class.Rd: +Rd.protobufFieldDescriptor * [r45] /pkg/man/protobufEnumDescriptor-class.Rd: added Rd for protobufEnumDescriptor * [r44] /pkg/R/00classes.R, /pkg/man/protobufDescriptor-class.Rd: added protobufDescriptor type * [r43] /pkg/man/protobufMessage-class.Rd: added Rd for protobufMessage class * [r42] /pkg/NAMESPACE, /pkg/R/debug_string.R, /pkg/man/P.Rd, /pkg/man/listPeople.Rd, /pkg/src/rprotobuf.cpp, /pkg/src/rprotobuf.h: added Rd for P, implement as.character for protobufMessage and protobufDescriptor * [r41] /pkg/src/constructors.cpp, /pkg/src/rprotobuf.cpp: minor fixes * [r40] /pkg/NAMESPACE, /pkg/R/serialize.R, /pkg/src/Makevars.in, /pkg/src/rprotobuf.h, /pkg/src/serialize.cpp: hooks for serialize method for protobufMessage * [r39] /pkg/NAMESPACE, /pkg/R/exceptions.R, /pkg/src/Makevars.in, /pkg/src/exceptions.cpp, /pkg/src/extractors.cpp, /pkg/src/rprotobuf.cpp, /pkg/src/rprotobuf.h: start playing with Exception handling, we need to call throwException instead of Rf_error in the c code 2009-10-30 Romain Francois * [r38] /pkg/R/exceptions.R, /pkg/src/extractors.cpp: extracting repeated fields, for now repeated messages are just returned as list of 'protobufMessage' objects * [r37] /pkg/NAMESPACE, /pkg/R/completion.R, /pkg/src/Makevars.in, /pkg/src/completion.cpp, /pkg/src/constructors.cpp, /pkg/src/extractors.cpp, /pkg/src/rprotobuf.h: implemented completions for Messages (giving field names) and Descriptors (fields, enums and nested types) * [r36] /pkg/src/constructors.cpp, /pkg/src/extractors.cpp, /pkg/src/fieldtypes.h, /pkg/src/rprotobuf.h: implement extraction of (almost) all types from messages with $ (missing ENUM type) * [r35] /pkg/R/00classes.R, /pkg/src/Makevars.in, /pkg/src/extractors.cpp, /pkg/src/fieldtypes.h, /pkg/src/rprotobuf.cpp, /pkg/src/rprotobuf.h: prepare the field extraction * [r34] /pkg/R/00classes.R, /pkg/src/constructors.cpp, /pkg/src/rprotobuf.cpp, /pkg/src/rprotobuf.h: implement new.protobufMessage that generates a new mutable Message using the generated Message factory * [r33] /pkg/src/constructors.cpp: some more doc in constructors.cpp * [r32] /pkg/R/internals.R, /pkg/src/constructors.cpp, /pkg/src/lookup.cpp, /pkg/src/rprotobuf.cpp, /pkg/src/rprotobuf.h: use R_NO_REMAP and Rf_ prefixes to avoid name clashes (install, error, ...) 2009-10-29 Romain Francois * [r31] /pkg/R/00classes.R, /pkg/R/internals.R, /pkg/src/rprotobuf.cpp, /pkg/src/rprotobuf.h: removed hard coded path * [r30] /pkg/R/00classes.R, /pkg/src/constructors.cpp, /pkg/src/rprotobuf.cpp, /pkg/src/rprotobuf.h: added enum types to $.Descriptor * [r29] /pkg/R/00classes.R: added $ extraction of nested types or fields by name * [r28] /pkg/R/00classes.R, /pkg/src/constructors.cpp: added $ extraction of nested types or fields by name * [r27] /pkg/src/Makevars.in, /pkg/src/constructors.cpp, /pkg/src/rprotobuf.cpp, /pkg/src/rprotobuf.h: added $ extraction of nested types or fields by name * [r26] /pkg/R/00classes.R, /pkg/src/rprotobuf.cpp: grab the descriptor from the pool in getProtobufDescriptor 2009-10-29 Dirk Eddelbuettel * [r25] /pkg/src/lookup.cpp: add two simple return() statements to make 'g++ -Wall' happy 2009-10-29 Romain Francois * [r24] /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/R/internals.R, /pkg/src/rprotobuf.cpp: grab the descriptor from the pool in getProtobufDescriptor * [r23] /pkg/R/00classes.R, /pkg/R/internals.R, /pkg/src/rprotobuf.cpp, /pkg/src/rprotobuf.h: collect information about a proto file * [r22] /pkg/src/lookup.cpp, /pkg/src/rprotobuf.h: objects returns character(0) instead of NULL, more consistent with attach( new.env() ) * [r21] /pkg/R/lookup.R, /pkg/src/Makevars.in, /pkg/src/lookup.cpp, /pkg/src/rprotobuf.cpp, /pkg/src/rprotobuf.h: added skeleton for lookup mechanism * [r20] /pkg/DESCRIPTION, /pkg/NAMESPACE, /pkg/R/00classes.R, /pkg/src/Makevars.in, /pkg/src/rprotobuf.cpp, /pkg/src/rprotobuf.h: skeleton for R S4 classes representing proto messages as external pointers 2009-10-27 Dirk Eddelbuettel * [r19] /pkg/src/Makevars.in: add CXXPICFLAGS which is needed on amd64 * [r18] /pkg/src/list_people_R.cpp: corrected listPeopleAsList() for special case of person 3 with no phones * [r17] /pkg/src/Makevars.in: support configure and automated build of all pieces incl conversion from proto file to header and source and then object * [r16] /pkg/src/list_people_R.cpp: suppress one more set of g++ warning, align function names * [r15] /pkg/cleanup: add more cleanup targets * [r14] /pkg/R/listPeople.R: align function names with C++ source * [r13] /pkg/configure, /pkg/configure.in: added configure support * [r12] /pkg/src/Makevars[DEL], /pkg/src/Makevars.in[CPY]: moved to Makevars.in and configure, also re-create header and source from proto * [r11] /pkg/src/addressbook.pb.cc[DEL], /pkg/src/addressbook.pb.h[DEL]: removed as they are now recreated * [r10] /pkg/configure.in: beginnings of a configure script, not yet ready * [r9] /pkg/NAMESPACE: added (nested) list support * [r8] /pkg/man/listPeople.Rd: documented (nested) list support * [r7] /pkg/R/listPeople.R: added (nested) list support * [r6] /pkg/src/list_people_R.cpp: add support for R lists, possibly nested this was a good test for Rcpp and should get folded into Rcpp * [r5] /pkg/src/addressbook.pb.cc, /pkg/src/addressbook.pb.h: rebuild with Ubuntu protoc -- probably need to farm this out to a proper Makefile or Makevar target 2009-10-22 Dirk Eddelbuettel * [r4] /pkg/src/list_people_R.cpp: add support for case of no phone entry * [r3] /pkg/src/Makevars: add -lpthread to PKG_LIBS * [r2] /pkg/DESCRIPTION, /pkg/NAMESPACE, /pkg/R, /pkg/R/listPeople.R, /pkg/README, /pkg/cleanup, /pkg/inst, /pkg/inst/examples, /pkg/inst/examples/AddressBookFile, /pkg/inst/examples/addressbook.proto, /pkg/man, /pkg/man/listPeople.Rd, /pkg/src, /pkg/src/Makevars, /pkg/src/addressbook.pb.cc, /pkg/src/addressbook.pb.h, /pkg/src/addressbook.proto, /pkg/src/list_people_R.cpp: A very basic first proof of concept package reading a binary protobuf file 2009-05-28 Stefan Theussl * [r1] /README, /pkg, /www, /www/index.php: R-Forge: updated repository structure RProtoBuf/man/0000755000176200001440000000000013005133352012702 5ustar liggesusersRProtoBuf/man/sizegets.Rd0000644000176200001440000000047613005133352015035 0ustar liggesusers\name{sizegets} \docType{methods} \alias{size<-} \alias{size<--methods} \alias{size<-,Message-method} \title{Set the size of a field} \description{ Sets the size of a repeated field. } \section{Methods}{ \describe{ \item{\code{signature(object = "Message")}}{ sets the size of a message field } }} \keyword{methods} RProtoBuf/man/ServiceDescriptor-class.Rd0000644000176200001440000000337513005133352017743 0ustar liggesusers\name{ServiceDescriptor-class} \Rdversion{1.1} \docType{class} \alias{ServiceDescriptor-class} \alias{as.character,ServiceDescriptor-method} \alias{toString,ServiceDescriptor-method} \alias{show,ServiceDescriptor-method} \alias{$,ServiceDescriptor-method} \alias{[[,ServiceDescriptor-method} \alias{length,ServiceDescriptor-method} \alias{method_count} \alias{method_count-methods} \alias{method_count,ServiceDescriptor-method} \alias{method} \alias{method-methods} \alias{method,ServiceDescriptor-method} \title{Class "ServiceDescriptor"} \description{R representation of Service Descriptors} \section{Objects from the Class}{ TODO } \section{Slots}{ \describe{ \item{\code{pointer}:}{External pointer to a \code{google::protobuf::ServiceDescriptor} C++ object } \item{\code{name}:}{fully qualified name of the service } } } \section{Methods}{ \describe{ \item{as.character}{\code{signature(x = "ServiceDescriptor")}: debug string of the service } \item{toString}{\code{signature(x = "ServiceDescriptor")}: debug string of the service} \item{show}{\code{signature(x = "ServiceDescriptor")}: ... } \item{$}{\code{signature(x = "ServiceDescriptor")}: invoke pseudo methods or retrieve method descriptors contained in this service descriptor. } \item{[[}{\code{signature(x = "ServiceDescriptor")}: extracts methods descriptors contained in this service descriptor} \item{length}{\code{signature(x = "ServiceDescriptor")}: number of \linkS4class{MethodDescriptor} } \item{method_count}{\code{signature(x = "ServiceDescriptor")}: number of \linkS4class{MethodDescriptor} } \item{method}{\code{signature(x = "ServiceDescriptor")}: retrieves a \linkS4class{MethodDescriptor} } } } \author{ Romain Francois } \keyword{classes} RProtoBuf/man/type.Rd0000644000176200001440000000246513005133352014161 0ustar liggesusers\name{type-methods} \alias{type} \alias{type-methods} \alias{cpp_type} \alias{cpp_type-methods} \alias{TYPE_DOUBLE} \alias{TYPE_FLOAT} \alias{TYPE_INT64} \alias{TYPE_UINT64} \alias{TYPE_INT32} \alias{TYPE_FIXED64} \alias{TYPE_FIXED32} \alias{TYPE_BOOL} \alias{TYPE_STRING} \alias{TYPE_GROUP} \alias{TYPE_MESSAGE} \alias{TYPE_BYTES} \alias{TYPE_UINT32} \alias{TYPE_ENUM} \alias{TYPE_SFIXED32} \alias{TYPE_SFIXED64} \alias{TYPE_SINT32} \alias{TYPE_SINT64} \alias{CPPTYPE_INT32} \alias{CPPTYPE_INT64} \alias{CPPTYPE_UINT32} \alias{CPPTYPE_UINT64} \alias{CPPTYPE_DOUBLE} \alias{CPPTYPE_FLOAT} \alias{CPPTYPE_BOOL} \alias{CPPTYPE_ENUM} \alias{CPPTYPE_STRING} \alias{CPPTYPE_MESSAGE} \title{Gets the type or the C++ type of a field} \description{ Gets the type or the C++ type of a field } \arguments{ \item{object}{A \linkS4class{FieldDescriptor} object.} \item{as.string}{If true, print a string representation of the type.} } \seealso{ The method is implemented for the \linkS4class{FieldDescriptor} class } \keyword{methods} \examples{ \dontrun{ proto.file <- system.file( "proto", "addressbook.proto", package = "RProtoBuf" ) Person <- P( "tutorial.Person", file = proto.file ) } \dontshow{Person <- P( "tutorial.Person" )} type(Person$id) type(Person$id, as.string=TRUE) cpp_type(Person$email) cpp_type(Person$email, TRUE) }RProtoBuf/man/asMessage.Rd0000644000176200001440000000144313005133352015103 0ustar liggesusers\name{asMessage} \alias{asMessage} \title{ coerce an object to a protobuf message } \description{ coerce an object to the \linkS4class{Message} class. This is a short-hand to the \link{as} method with the \code{Class} argument set to "Message" } \usage{ asMessage(x, ...) } \arguments{ \item{x}{object to coerce to a protobuf message} \item{\dots}{Passed to \code{\link{as}} } } \value{ a \linkS4class{Message} object } \author{ Romain Francois } \examples{ # coerce a message type descriptor to a message asMessage( tutorial.Person ) # coerce a enum descriptor asMessage( tutorial.Person.PhoneType ) # coerce a field descriptor asMessage( tutorial.Person$email ) # coerce a file descriptor asMessage( fileDescriptor( tutorial.Person ) ) } \keyword{ programming } RProtoBuf/man/ByteCount-methods.Rd0000644000176200001440000000050313005133352016544 0ustar liggesusers\name{ByteCount-methods} \docType{methods} \alias{ByteCount} \alias{ByteCount-methods} \title{The number of bytes read/written since the object was created} \description{ The number of bytes read/written since the object was created } \seealso{ \linkS4class{ZeroCopyInputStream} implements ByteCount. } \keyword{methods} RProtoBuf/man/FileInputStream-class.Rd0000644000176200001440000000322613005133352017352 0ustar liggesusers\name{FileInputStream-class} \Rdversion{1.1} \docType{class} \alias{FileInputStream-class} \alias{close,FileInputStream-method} \alias{GetErrno,FileInputStream-method} \alias{SetCloseOnDelete,FileInputStream-method} \title{Class "FileInputStream" } \description{A \linkS4class{ZeroCopyInputStream} reading from a file} \section{Objects from the Class}{ Objects can be created by the \link{FileInputStream} function } \section{Slots}{ \describe{ \item{\code{pointer}:}{ External pointer to the \code{google::protobuf::io::FileInputStream} C++ object} } } \section{Extends}{ Class \code{"\linkS4class{ZeroCopyInputStream}"}, directly. } \section{Methods}{ \describe{ \item{close}{\code{signature(con="FileInputStream")}: Flushes any buffers and closes the underlying file. Returns false if an error occurs during the process; use \code{GetErrno} to examine the error } \item{GetErrno}{\code{signature(object="FileInputStream")}: If an I/O error has occurred on this file descriptor, this is the errno from that error. Otherwise, this is zero. Once an error occurs, the stream is broken and all subsequent operations will fail. } \item{SetCloseOnDelete}{\code{signature(object="FileInputStream")}: set the close on delete behavior. } } See \linkS4class{ZeroCopyInputStream} for inherited methods } \references{ The \code{FileInputStream} class from the protobuf C++ library. \url{http://code.google.com/apis/protocolbuffers/docs/reference/cpp/google.protobuf.io.zero_copy_stream_impl_lite.html#FileInputStream} } \author{ Romain Francois } \seealso{ \linkS4class{ZeroCopyInputStream} for methods } \keyword{classes} RProtoBuf/man/set.Rd0000644000176200001440000000060113005133352013761 0ustar liggesusers\name{set-methods} \docType{methods} \alias{set} \alias{set-methods} \alias{set,Message-method} \title{set a subset of values of a repeated field of a message} \description{ set a subset of values of a repeated field of a message } \section{Methods}{ \describe{ \item{\code{signature(object = "Message")}}{set a subset of values of a repeated field of a message} }} \keyword{methods} RProtoBuf/man/FileOutputStream-methods.Rd0000644000176200001440000000076013005133352020111 0ustar liggesusers\name{FileOutputStream-methods} \docType{methods} \alias{FileOutputStream} \alias{FileOutputStream-methods} \alias{FileOutputStream,character,integer,logical-method} \title{Creates an FileOutputStream} \description{ Constructor for \linkS4class{FileOutputStream} objects } \section{Methods}{ \describe{ \item{\code{signature(filename = "character", block_size = "logical", close.on.delete = "logical" )}}{Creates a \linkS4class{FileOutputStream} writing to the given file.} }} \keyword{methods} RProtoBuf/man/descriptor.Rd0000644000176200001440000000065513005133352015355 0ustar liggesusers\name{descriptor-methods} \docType{methods} \alias{descriptor} \alias{descriptor-methods} \alias{descriptor,Message-method} \title{Get the descriptor of a message} \description{ Get the \linkS4class{Descriptor} associated with a \linkS4class{Message} } \section{Methods}{ \describe{ \item{\code{signature(object = "Message")}}{ Get the descriptor of the message, as a \linkS4class{Descriptor} instance } }} \keyword{methods} RProtoBuf/man/fileDescriptor.Rd0000644000176200001440000000233713005133352016154 0ustar liggesusers\name{fileDescriptor-methods} \docType{methods} \alias{fileDescriptor} \alias{fileDescriptor-methods} \alias{fileDescriptor,Descriptor-method} \alias{fileDescriptor,Message-method} \alias{fileDescriptor,EnumDescriptor-method} \alias{fileDescriptor,FieldDescriptor-method} \alias{fileDescriptor,ServiceDescriptor-method} \alias{fileDescriptor,MethodDescriptor-method} \title{gets the file descriptor of an object} \description{ Gets the file descriptor of an object } \section{Methods}{ \describe{ \item{\code{signature(object = "Descriptor")}}{ retrieves the file descriptor associated with this descriptor} \item{\code{signature(object = "Message")}}{ retrieves the file descriptor associated with the descriptor of this message } \item{\code{signature(object = "EnumDescriptor")}}{ retrieves the file descriptor associated with the enum descriptor } \item{\code{signature(object = "FieldDescriptor")}}{ retrieves the file descriptor associated with the field descriptor } \item{\code{signature(object = "ServiceDescriptor")}}{ retrieves the file descriptor associated with the service descriptor } \item{\code{signature(object = "MethodDescriptor")}}{ retrieves the file descriptor associated with the method descriptor } }} \keyword{methods} RProtoBuf/man/is_extension.Rd0000644000176200001440000000056313005133352015704 0ustar liggesusers\name{is_extension-methods} \alias{is_extension} \alias{is_extension-methods} \title{Indicates if a field descriptor is an extension} \description{ Indicates if a field descriptor is an extension } \seealso{ The method is implemented for the \linkS4class{FieldDescriptor} class } \keyword{methods} \examples{ Person <- P( "tutorial.Person" ) is_extension(Person$id) }RProtoBuf/man/has.Rd0000644000176200001440000000311713005133352013746 0ustar liggesusers\name{has-methods} \docType{methods} \alias{has} \alias{has-methods} \alias{has,Message-method} \title{Indicates if an object has the given field set} \description{ This generic method, currently implemented for \linkS4class{Message} and \linkS4class{EnumDescriptor} indicates if the message or enum descriptor has the given field set. For messages and non-repeated fields, a call to the \code{HasField} method of the corresponding \code{Message} is issued. For messages and repeated fields, a call to the \code{FieldSize} method is issued, and the message is declared to have the field if the size is greater than 0. \code{NULL} is returned if the descriptor for the message does not contain the given field at all. For EnumDescriptors, a boolean value indicates if the given name is present in the enum definition. } \section{Methods}{ \describe{ \item{has}{\code{signature(object = "Message")}: Indicates if the message has a given field.} \item{has}{\code{signature(object = "EnumDescriptor")}: Indicates if the EnumDescriptor has a given named element.} } } \examples{ unitest.proto.file <- system.file("unitTests", "data", "unittest.proto", package = "RProtoBuf" ) readProtoFiles(file = unitest.proto.file) test <- new(protobuf_unittest.TestAllTypes) test$has("optional_int32") # FALSE test$add("repeated_int32", 1:10) test$has("repeated_int32") # TRUE test$has("nonexistant") # NULL has(protobuf_unittest.TestAllTypes$NestedEnum, "FOO") has(protobuf_unittest.TestAllTypes$NestedEnum, "BAR") has(protobuf_unittest.TestAllTypes$NestedEnum, "XXX") } \keyword{methods} RProtoBuf/man/Skip-methods.Rd0000644000176200001440000000024313005133352015537 0ustar liggesusers\name{Skip-methods} \docType{methods} \alias{Skip} \alias{Skip-methods} \title{Skips a number of bytes} \description{ Skips a number of bytes } \keyword{methods} RProtoBuf/man/P.Rd0000644000176200001440000000157113005133352013374 0ustar liggesusers\name{P} \alias{P} \title{Protocol Buffer descriptor importer} \description{ The \code{P} function searches for a protocol message descriptor in the descriptor pool. } \usage{ P(type, file) } \arguments{ \item{type}{Fully qualified type name of the protocol buffer or extension} \item{file}{optional proto file. If given, the definition contained in the file is first registered with the pool of message descriptors} } \value{ An object of class \linkS4class{Descriptor} for message types or \linkS4class{FieldDescriptor} for extensions. An error is generated otherwise. } \author{ Romain Francois } \examples{ \dontrun{ proto.file <- system.file( "proto", "addressbook.proto", package = "RProtoBuf" ) Person <- P( "tutorial.Person", file = proto.file ) } \dontshow{ Person <- P("tutorial.Person") } cat(as.character( Person )) } \keyword{ interface } RProtoBuf/man/add.Rd0000644000176200001440000000120113005133352013713 0ustar liggesusers\name{add-methods} \docType{methods} \alias{add} \alias{add-methods} \alias{add,Message-method} \title{add elements of a repeated field of a message} \description{ Add elements to a repeated field of a message. } \section{Methods}{ \describe{ \item{\code{signature(object = "Message")}}{add elements to a repeated field of a message} }} \examples{ unitest.proto.file <- system.file("unitTests", "data", "unittest.proto", package = "RProtoBuf" ) readProtoFiles(file = unitest.proto.file) test <- new(protobuf_unittest.TestAllTypes) test$add("repeated_int32", 1) test$add("repeated_int32", 2:10) test$repeated_int32 } \keyword{methods} RProtoBuf/man/FieldDescriptor-class.Rd0000644000176200001440000001257113005133352017364 0ustar liggesusers\name{FieldDescriptor-class} \Rdversion{1.1} \docType{class} \alias{FieldDescriptor-class} \alias{show,FieldDescriptor-method} \alias{$,FieldDescriptor-method} \alias{as.character,FieldDescriptor-method} \alias{toString,FieldDescriptor-method} \alias{containing_type,FieldDescriptor-method} \alias{is_extension,FieldDescriptor-method} \alias{number,FieldDescriptor-method} \alias{type,FieldDescriptor-method} \alias{cpp_type,FieldDescriptor-method} \alias{label,FieldDescriptor-method} \alias{is_required} \alias{is_optional} \alias{is_repeated} \alias{is_required-methods} \alias{is_optional-methods} \alias{is_repeated-methods} \alias{is_required,FieldDescriptor-method} \alias{is_optional,FieldDescriptor-method} \alias{is_repeated,FieldDescriptor-method} \alias{has_default_value} \alias{has_default_value-methods} \alias{has_default_value,FieldDescriptor-method} \alias{default_value} \alias{default_value-methods} \alias{default_value,FieldDescriptor-method} \alias{message_type} \alias{message_type-methods} \alias{message_type,FieldDescriptor-method} \alias{enum_type,FieldDescriptor,missing,missing-method} \title{Class "FieldDescriptor"} \description{R representation of message type field descriptor. This is a thin wrapper around the C++ class \code{FieldDescriptor} } \section{Objects from the Class}{ Objects typically are retrieved from \linkS4class{FieldDescriptor} } \section{Slots}{ \describe{ \item{\code{pointer}:}{external pointer to the \code{FieldDescriptor} c++ object } \item{\code{name}:}{ name of the field within the message type } \item{\code{full_name}:}{Fully qualified name of the field} \item{\code{type}:}{Fully qualified name of the type that contains this field } } } \section{Methods}{ \describe{ \item{show}{\code{signature(object = "FieldDescriptor")}: small description } \item{as.character}{\code{signature(x = "FieldDescriptor")}: returns the debug string of the field descriptor. This is retrieved by a call to the \code{DebugString} method of the FieldDescriptor object. } \item{toString}{\code{signature(x = "FieldDescriptor")}: same as \code{as.character} } \item{$}{\code{signature(x = "FieldDescriptor")}: used to invoke pseudo methods } \item{containing_type}{\code{signature(object = "FieldDescriptor")} : returns a \linkS4class{Descriptor} of the message type that contains this field descriptor.} \item{is_extension}{\code{signature(object = "FieldDescriptor")} : indicates if this is an extension.} \item{number}{\code{signature(object = "FieldDescriptor")} : gets the declared tag number of this field.} \item{type}{\code{signature(object = "FieldDescriptor")} : type of this field.} \item{cpp_type}{\code{signature(object = "FieldDescriptor")} : c++ type of this field.} \item{label}{\code{signature(object = "FieldDescriptor")} : label of this field.} \item{is_required}{\code{signature(object = "FieldDescriptor")} : is this field required.} \item{is_optional}{\code{signature(object = "FieldDescriptor")} : is this field optional.} \item{is_repeated}{\code{signature(object = "FieldDescriptor")} : is this field repeated.} \item{has_default_value}{\code{signature(object = "FieldDescriptor")} : indicates if this field has a default value.} \item{default_value}{\code{signature(object = "FieldDescriptor")} : the default value of this field.} \item{message_type}{\code{signature(object = "FieldDescriptor")} : the \linkS4class{Descriptor} for the associated message type. Generates an error if this field is not a message type field.} \item{enum_type}{\code{signature(object = "FieldDescriptor")} : the \linkS4class{EnumDescriptor} for the associated enum type.Generates an error if this field is not an enum type field } } } \references{ The \code{FieldDescriptor} C++ class } \author{ Romain Francois } \seealso{ \linkS4class{Descriptor} } \examples{ \dontrun{ # example proto file supplied with this package proto.file <- system.file( "proto", "addressbook.proto", package = "RProtoBuf" ) # reading a proto file and creating the descriptor Person <- P( "tutorial.Person", file = proto.file ) } \dontshow{Person <- P("tutorial.Person") } # field descriptor object Person$email # debug string as.character( Person$email ) # or as a pseudo method Person$email$as.character() Person$email$is_required() Person$email$is_optional() Person$email$is_repeated() Person$email$has_default_value() Person$email$default_value() Person$email$is_extension() # Get the default values has_default_value(Person$id) has_default_value(Person$email) has_default_value(Person$phone) default_value(Person$id) default_value(Person$email) default_value(Person$phone) # Get the types of field descriptors type(Person$id) type(Person$id, as.string=TRUE) cpp_type(Person$email) cpp_type(Person$email, TRUE) # Get the label of a field descriptor label(Person$id) label(Person$email) label(Person$phone) label(Person$id, TRUE) label(Person$email, TRUE) label(Person$phone, TRUE) LABEL_OPTIONAL LABEL_REQUIRED LABEL_REPEATED # Test if a field is optional is_optional(Person$id) is_optional(Person$email) is_optional(Person$phone) # Test if a field is repeated is_repeated(Person$id) is_repeated(Person$email) is_repeated(Person$phone) # Test if a field is required is_required(Person$id) is_required(Person$email) is_required(Person$phone) # Return the class of a message field message_type(Person$phone) } \keyword{classes} RProtoBuf/man/ConnectionInputStream-class.Rd0000644000176200001440000000145413005133352020573 0ustar liggesusers\name{ConnectionInputStream-class} \Rdversion{1.1} \docType{class} \alias{ConnectionInputStream-class} \title{Class "ConnectionInputStream" } \description{A \linkS4class{ZeroCopyInputStream} reading from a binary R connection} \section{Objects from the Class}{ Objects can be created by the \link{ConnectionInputStream} function } \section{Slots}{ \describe{ \item{\code{pointer}:}{ External pointer to the \code{rprotobuf::ConnectionInputStream} C++ object} } } \section{Extends}{ Class \code{"\linkS4class{ZeroCopyInputStream}"}, directly. } \section{Methods}{ See \linkS4class{ZeroCopyInputStream} } \references{ The internal C++ class \code{ConnectionInputStream} } \author{ Romain Francois } \seealso{ \linkS4class{ZeroCopyInputStream} for methods } \keyword{classes} RProtoBuf/man/nested_type.Rd0000644000176200001440000000051013005133352015510 0ustar liggesusers\name{nested_type-methods} \alias{nested_type} \alias{nested_type-methods} \title{Extract a message type descriptor for a nested type} \description{ Extract a \linkS4class{Descriptor} nested in another \linkS4class{Descriptor} } \seealso{ The method is implemented for the \linkS4class{Descriptor} class } \keyword{methods} RProtoBuf/man/swap.Rd0000644000176200001440000000107213005133352014143 0ustar liggesusers\name{swap-methods} \docType{methods} \alias{swap} \alias{swap-methods} \alias{swap,Message-method} \title{swap elements of a repeated field of a message} \description{ swap elements of a repeated field of a message. } \section{Methods}{ \describe{ \item{\code{signature(object = "Message")}}{swap elements of a repeated field of a message} }} \references{ See the \code{SwapElements} of the \code{Reflection} class, part of the protobuf library. \url{http://code.google.com/apis/protocolbuffers/docs/reference/cpp/google.protobuf.message.html} } \keyword{methods} RProtoBuf/man/ArrayInputStream-class.Rd0000644000176200001440000000302513005133352017546 0ustar liggesusers\name{ArrayInputStream-class} \Rdversion{1.1} \docType{class} \alias{ArrayInputStream-class} \title{Class "ArrayInputStream" } \description{A \linkS4class{ZeroCopyInputStream} backed by an in-memory array of bytes} \section{Objects from the Class}{ Objects can be created by the \link{ArrayInputStream} function } \section{Slots}{ \describe{ \item{\code{pointer}:}{ External pointer to the \code{google::protobuf::io::ArrayInputStream} C++ object} } } \section{Extends}{ Class \code{"\linkS4class{ZeroCopyInputStream}"}, directly. } \section{Methods}{ See \linkS4class{ZeroCopyInputStream} } \references{ The \code{ArrayInputStream} class from the protobuf C++ library. \url{http://code.google.com/apis/protocolbuffers/docs/reference/cpp/google.protobuf.io.zero_copy_stream_impl_lite.html#ArrayInputStream} } \author{ Romain Francois } \seealso{ \linkS4class{ZeroCopyInputStream} for methods } \examples{ stream <- ArrayInputStream(as.raw(0:10)) stream$ReadRaw(5) stringsstream <- ArrayInputStream(as.raw(c(0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67))) stringsstream$ReadString(7) intstream <- ArrayInputStream(as.raw(c(0x9e, 0xa7, 0x05))) intstream$ReadVarint32() } % local({ % stream <- ArrayInputStream( as.raw(0:10) ) % stopifnot( identical( stream$Next(), as.raw(0:10) ) ) % stream$BackUp( 5 ) % stopifnot( identical( stream$Next(), as.raw(6:10) ) ) % % # limiting the block size % stream <- ArrayInputStream( as.raw(0:10), 5 ) % stopifnot( identical(length( stream$Next() ), 5L ) ) % }) \keyword{classes} RProtoBuf/man/MethodDescriptor-class.Rd0000644000176200001440000000276313005133352017563 0ustar liggesusers\name{MethodDescriptor-class} \Rdversion{1.1} \docType{class} \alias{MethodDescriptor-class} \alias{as.character,MethodDescriptor-method} \alias{toString,MethodDescriptor-method} \alias{$,MethodDescriptor-method} \alias{$<-,MethodDescriptor-method} \alias{input_type} \alias{input_type-methods} \alias{input_type,MethodDescriptor-method} \alias{output_type} \alias{output_type-methods} \alias{output_type,MethodDescriptor-method} \title{Class "MethodDescriptor"} \description{R representation of Service Descriptors} \section{Objects from the Class}{ TODO } \section{Slots}{ \describe{ \item{\code{pointer}:}{External pointer to a \code{google::protobuf::MethodDescriptor} C++ object } \item{\code{name}:}{fully qualified name of the method} \item{\code{service}:}{fully qualified name of the service that defines this method} } } \section{Methods}{ \describe{ \item{as.character}{\code{signature(x = "MethodDescriptor")}: debug string of the method } \item{toString}{\code{signature(x = "MethodDescriptor")}: debug string of the method} \item{$}{\code{signature(x = "MethodDescriptor")}: ... } \item{$<-}{\code{signature(x = "MethodDescriptor")}: ... } \item{input_type}{\code{signature(object = "MethodDescriptor")}: the \linkS4class{Descriptor} of the input type of the method} \item{output_type}{\code{signature(object = "MethodDescriptor")}: the \linkS4class{Descriptor} of the output type of the method } } } \author{ Romain Francois } \keyword{classes} RProtoBuf/man/ConnectionOutputStream-methods.Rd0000644000176200001440000000074313005133352021332 0ustar liggesusers\name{ConnectionOutputStream-methods} \docType{methods} \alias{ConnectionOutputStream} \alias{ConnectionOutputStream-methods} \alias{ConnectionOutputStream,connection-method} \title{Creates an ConnectionOutputStream} \description{ Constructor for \linkS4class{ConnectionOutputStream} objects } \section{Methods}{ \describe{ \item{\code{signature(object="connection")}}{ Creates a \linkS4class{ConnectionOutputStream} writing to the given R binary connection.} }} \keyword{methods} RProtoBuf/man/enum_type.Rd0000644000176200001440000000050113005133352015172 0ustar liggesusers\name{enum_type-methods} \alias{enum_type} \alias{enum_type-methods} \title{Extract an enum type descriptor for a nested type} \description{ Extract a \linkS4class{EnumDescriptor} contained in a \linkS4class{Descriptor} } \seealso{ The method is implemented for the \linkS4class{Descriptor} class } \keyword{methods} RProtoBuf/man/EnumDescriptor-class.Rd0000644000176200001440000000732613005133352017247 0ustar liggesusers\name{EnumDescriptor-class} \Rdversion{1.1} \docType{class} \alias{EnumDescriptor-class} \alias{show,EnumDescriptor-method} \alias{has,EnumDescriptor-method} \alias{as.character,EnumDescriptor-method} \alias{toString,EnumDescriptor-method} \alias{$,EnumDescriptor-method} \alias{containing_type,EnumDescriptor-method} \alias{length,EnumDescriptor-method} \alias{value_count} \alias{value_count-methods} \alias{value_count,EnumDescriptor-method} \alias{value} \alias{value-methods} \alias{value,EnumDescriptor-method} \alias{[[,EnumDescriptor-method} \alias{names,EnumDescriptor-method} \title{Class "EnumDescriptor" } \description{ R representation of an enum descriptor. This is a thin wrapper around the \code{EnumDescriptor} c++ class. } \section{Objects from the Class}{ Objects of this class are typically retrieved as members of \linkS4class{Descriptor} objects } \section{Slots}{ \describe{ \item{\code{pointer}:}{external pointer to the \code{EnumDescriptor} instance} \item{\code{name}:}{ simple name of the enum } \item{\code{full_name}:}{fully qualified name } \item{\code{type}:}{fully qualified name of the type that contains this enumeration} } } \section{Methods}{ \describe{ \item{show}{\code{signature(object = "EnumDescriptor")}: small information } \item{as.character}{\code{signature(x = "EnumDescriptor")}: returns the debug string of the enum descriptor. This is retrieved by a call to the \code{DebugString} method of the EnumDescriptor object. } \item{toString}{\code{signature(x = "EnumDescriptor")}: same as \code{as.character} } \item{$}{\code{signature(x = "EnumDescriptor")}: get the number associated with the name} \item{has}{\code{signature(object = "EnumDescriptor")}: indicate if the given name is a constant present in this enum.} \item{containing_type}{\code{signature(object = "EnumDescriptor")} : returns a \linkS4class{Descriptor} of the message type that contains this enum descriptor, or NULL if this is a top level enum descriptor.} \item{length}{\code{signature(x = "EnumDescriptor")} : number of constants in this enum.} \item{value_count}{\code{signature(object = "EnumDescriptor")} : number of constants in this enum.} \item{value}{\code{signature(object = "EnumDescriptor")} : extracts an \linkS4class{EnumValueDescriptor}. Exactly one argument of \code{index}, \code{number} or \code{name} has to be used. If \code{index} is used, the enum value descriptor is retrieved by position, using the \code{value} method of the C++ class. If \code{number} is used, the enum value descriptor is retrieved using the value of the constant, using the \code{FindValueByNumber} C++ method. If \code{name} is used, the enum value descriptor is retrieved using the name of the constant, using the \code{FindValueByName} C++ method. } \item{[[}{\code{signature(x = "EnumDescriptor")}: extracts field identified by its name or declared tag number} \item{names}{\code{signature(x = "EnumDescriptor")} : extracts names of this enum} } } \references{ The \code{EnumDescriptor} C++ class } \author{ Romain Francois } \seealso{The \linkS4class{Descriptor} class} \examples{ \dontrun{ # example proto file supplied with this package proto.file <- system.file( "proto", "addressbook.proto", package = "RProtoBuf" ) # reading a proto file and creating the descriptor Person <- P( "tutorial.Person", file = proto.file ) } \dontshow{Person <- P("tutorial.Person") } # enum type Person$PhoneType has(Person$PhoneType, "MOBILE") has(Person$PhoneType, "HOME") has(Person$PhoneType, "WORK") has(Person$PhoneType, "FOOBAR") length(Person$PhoneType) } \keyword{classes} RProtoBuf/man/FileInputStream-methods.Rd0000644000176200001440000000075313005133352017712 0ustar liggesusers\name{FileInputStream-methods} \docType{methods} \alias{FileInputStream} \alias{FileInputStream-methods} \alias{FileInputStream,character,integer,logical-method} \title{Creates an FileInputStream} \description{ Constructor for \linkS4class{FileInputStream} objects } \section{Methods}{ \describe{ \item{\code{signature(filename = "character", block_size = "logical", close.on.delete = "logical" )}}{Creates a \linkS4class{FileInputStream} reading from the given file.} }} \keyword{methods} RProtoBuf/man/RpcHTTP-class.Rd0000644000176200001440000000121013005133352015512 0ustar liggesusers\name{RpcHTTP-class} \Rdversion{1.1} \docType{class} \alias{RpcHTTP-class} \title{Class "RpcHTTP" } \description{Support for protobuf rpc over HTTP} \section{Objects from the Class}{ Objects can be created by calls of the form \code{new("RpcHTTP", host = "somehost", port = port.number, root = "" )} } \section{Slots}{ \describe{ \item{\code{host}:}{Host name} \item{\code{port}:}{port number} \item{\code{root}:}{root directory of the protobuf http server} } } \author{ Romain Francois } \seealso{ \link{invoke} uses objects of this class to perform a method invocation over http. } \keyword{classes} RProtoBuf/man/FileDescriptor-class.Rd0000644000176200001440000000330513005133352017213 0ustar liggesusers\name{FileDescriptor-class} \Rdversion{1.1} \docType{class} \alias{FileDescriptor-class} \alias{as.character,FileDescriptor-method} \alias{toString,FileDescriptor-method} \alias{$,FileDescriptor-method} \alias{show,FileDescriptor-method} \alias{name,FileDescriptor-method} \title{Class "FileDescriptor"} \description{Class "FileDescriptor"} \section{Objects from the Class}{ Objects are usually created using the \code{\link{fileDescriptor}} method } \section{Slots}{ \describe{ \item{\code{pointer}:}{external pointer to a \code{google::protobuf::FileDescriptor} C++ object } \item{\code{package}:}{the package name defined in the file, e.g. 'tutorial'.} \item{\code{filename}:}{the filename of this FileDescriptor} } } \section{Methods}{ \describe{ \item{$}{\code{signature(x = "FileDescriptor")}: used to invoke a pseudo method of the file descriptor or get a top level message, enum or service descriptor} \item{toString}{\code{signature(x = "FileDescriptor" )} : gets the debug string} \item{as.character}{\code{signature(x = "FileDescriptor" )} : gets the debug string} \item{show}{\code{signature(x = "FileDescriptor" )} : prints small text} \item{name}{\code{signature(object = "FileDescriptor" )} : name of the file} } } \references{ The \url{http://code.google.com/apis/protocolbuffers/docs/reference/cpp/google.protobuf.descriptor.html#FileDescriptor} } \author{ Romain Francois } \keyword{classes} \seealso{ \linkS4class{Descriptor} } \examples{ # example proto file supplied with this package desc <- P("tutorial.Person") person <- new(desc) person$fileDescriptor() name(person$fileDescriptor()) # [1] "addressbook.proto" as.character(person$fileDescriptor()) } RProtoBuf/man/ArrayOutputStream-methods.Rd0000644000176200001440000000254613005133352020314 0ustar liggesusers\name{ArrayOutputStream-methods} \docType{methods} \alias{ArrayOutputStream} \alias{ArrayOutputStream-methods} \alias{ArrayOutputStream,integer,missing-method} \alias{ArrayOutputStream,integer,integer-method} \alias{ArrayOutputStream,integer,numeric-method} \alias{ArrayOutputStream,numeric,missing-method} \alias{ArrayOutputStream,numeric,integer-method} \alias{ArrayOutputStream,numeric,numeric-method} \title{Creates an ArrayOutputStream} \description{ Constructor for \linkS4class{ArrayOutputStream} objects } \section{Methods}{ \describe{ \item{\code{signature(size = "integer", block_size = "missing" )}}{Creates a \linkS4class{ArrayOutputStream} using of the given size} \item{\code{signature(size = "integer", block_size = "integer" )}}{Creates a \linkS4class{ArrayOutputStream} ... same with block size. } \item{\code{signature(size = "integer", block_size = "numeric" )}}{Creates a \linkS4class{ArrayOutputStream} ... same with block size. } \item{\code{signature(size = "numeric", block_size = "missing" )}}{Creates a \linkS4class{ArrayOutputStream} using of the given size} \item{\code{signature(size = "numeric", block_size = "integer" )}}{Creates a \linkS4class{ArrayOutputStream} ... same with block size. } \item{\code{signature(size = "numeric", block_size = "numeric" )}}{Creates a \linkS4class{ArrayOutputStream} ... same with block size. } }} \keyword{methods} RProtoBuf/man/completion.Rd0000644000176200001440000000411713005133352015345 0ustar liggesusers\name{completion} \alias{.DollarNames.Message} \alias{.DollarNames.Descriptor} \alias{.DollarNames.EnumDescriptor} \alias{.DollarNames.FieldDescriptor} \alias{.DollarNames.FileDescriptor} \alias{.DollarNames.ServiceDescriptor} \alias{.DollarNames.MethodDescriptor} \alias{.DollarNames.ZeroCopyInputStream} \alias{.DollarNames.ZeroCopyOutputStream} \title{ Completion support for protocol buffer messages and descriptors } \description{ These functions support completion of protocol buffer messages and descriptors. } \usage{ \S3method{.DollarNames}{Message}(x, pattern = "") \S3method{.DollarNames}{Descriptor}(x, pattern = "") \S3method{.DollarNames}{EnumDescriptor}(x, pattern = "") \S3method{.DollarNames}{FieldDescriptor}(x, pattern = "") \S3method{.DollarNames}{FileDescriptor}(x, pattern = "") \S3method{.DollarNames}{ServiceDescriptor}(x, pattern = "") \S3method{.DollarNames}{MethodDescriptor}(x, pattern = "") \S3method{.DollarNames}{ZeroCopyInputStream}(x, pattern = "") \S3method{.DollarNames}{ZeroCopyOutputStream}(x, pattern = "") } \arguments{ \item{x}{message (\linkS4class{Message}) or descriptor (\linkS4class{Descriptor}) } \item{pattern}{filter} } \value{ Character vector containing potential completions. For \linkS4class{Message} objects, completions are the fields of the message and a set of pseudo methods ("has") For \linkS4class{EnumDescriptor} objects, completions are the names of the possible constants For \linkS4class{Descriptor} objects, completions are the names of the fields, enum types and nested message types defined in the associated message type. For \linkS4class{FileDescriptor} objects, completions are the names of the top-level descriptors (message, enum or service) contained in the associated file, or pseudo methods. } \author{ Romain Francois } \examples{ # creating a prototype message from the descriptor p <- new( tutorial.Person ) .DollarNames( p ) .DollarNames( tutorial.Person ) # but this is usually used with the expansion on the command line # means "press the TAB key" # p$ # Person$ } \keyword{ programming } RProtoBuf/man/BackUp-methods.Rd0000644000176200001440000000041513005133352015777 0ustar liggesusers\name{BackUp-methods} \docType{methods} \alias{BackUp} \alias{BackUp-methods} \title{Backs up a number of bytes from a stream} \description{ Backs up a number of bytes from a stream } \seealso{ \linkS4class{ZeroCopyInputStream} implements BackUp. } \keyword{methods} RProtoBuf/man/ZeroCopyOutputStream-class.Rd0000644000176200001440000000533013005133352020444 0ustar liggesusers\name{ZeroCopyOutputStream-class} \Rdversion{1.1} \docType{class} \alias{ZeroCopyOutputStream-class} \alias{ByteCount,ZeroCopyOutputStream-method} \alias{BackUp,ZeroCopyOutputStream-method} \alias{Next,ZeroCopyOutputStream,raw-method} \alias{$,ZeroCopyOutputStream-method} \alias{WriteRaw} \alias{WriteRaw-methods} \alias{WriteRaw,ZeroCopyOutputStream,raw-method} \alias{WriteString} \alias{WriteString-methods} \alias{WriteString,ZeroCopyOutputStream,character-method} \alias{WriteLittleEndian32} \alias{WriteLittleEndian32-methods} \alias{WriteLittleEndian32,ZeroCopyOutputStream,integer-method} \alias{WriteLittleEndian32,ZeroCopyOutputStream,numeric-method} \alias{WriteLittleEndian32,ZeroCopyOutputStream,raw-method} \alias{WriteLittleEndian64} \alias{WriteLittleEndian64-methods} \alias{WriteLittleEndian64,ZeroCopyOutputStream,integer-method} \alias{WriteLittleEndian64,ZeroCopyOutputStream,numeric-method} \alias{WriteLittleEndian64,ZeroCopyOutputStream,raw-method} \alias{WriteVarint32} \alias{WriteVarint32-methods} \alias{WriteVarint32,ZeroCopyOutputStream,integer-method} \alias{WriteVarint32,ZeroCopyOutputStream,numeric-method} \alias{WriteVarint32,ZeroCopyOutputStream,raw-method} \alias{WriteVarint64} \alias{WriteVarint64-methods} \alias{WriteVarint64,ZeroCopyOutputStream,integer-method} \alias{WriteVarint64,ZeroCopyOutputStream,numeric-method} \alias{WriteVarint64,ZeroCopyOutputStream,raw-method} \title{Virtual Class "ZeroCopyOutputStream" } \description{R wrapper for the ZeroCopyOutputStream c++ class} \section{Objects from the Class}{ This is a virtual class } \section{Slots}{ \describe{ \item{\code{pointer}:}{external pointer to the \code{google::protobuf::io::ZeroCopyOutputStream} object} } } \section{Methods}{ \describe{ \item{$}{\code{signature(x="ZeroCopyOutputStream")}: invokes a method} \item{Next}{\code{signature(object="ZeroCopyOutputStream", payload = "raw" )}: push the raw vector into the stream. Returns the number of bytes actually written.} \item{BackUp}{\code{signature(object="ZeroCopyOutputStream")}: Backs up a number of bytes, so that the end of the last buffer returned by \code{Next} is not actually written.} \item{ByteCount}{\code{signature(object="ZeroCopyOutputStream")}: Returns the total number of bytes written since this object was created. } \item{WriteRaw}{\code{signature(object="ZeroCopyOuputStream", payload = "raw"}: write the raw bytes to the stream} } } \author{ Romain Francois } \references{ The \code{google::protobuf::io::ZeroCopyOutputStream} C++ class. \url{http://code.google.com/apis/protocolbuffers/docs/reference/cpp/google.protobuf.io.zero_copy_stream.html#ZeroCopyOutputStream} } \seealso{ TODO: add classes that extend } \keyword{classes} RProtoBuf/man/field_count.Rd0000644000176200001440000000035613005133352015470 0ustar liggesusers\name{field_count-methods} \alias{field_count} \alias{field_count-methods} \title{The number of fields} \description{ The number of fields } \seealso{ The method is implemented for the \linkS4class{Descriptor} class } \keyword{methods} RProtoBuf/man/number.Rd0000644000176200001440000000115213005133352014460 0ustar liggesusers\name{number-methods} \alias{number} \alias{number-methods} \title{Gets the declared tag number of a field} \description{ Gets the declared tag number of a field } \seealso{ The method is implemented for \linkS4class{FieldDescriptor} and \linkS4class{EnumValueDescriptor} classes. } \keyword{methods} \examples{ \dontrun{ proto.file <- system.file( "proto", "addressbook.proto", package = "RProtoBuf" ) Person <- P( "tutorial.Person", file = proto.file ) } \dontshow{ Person <- P("tutorial.Person") } number(Person$id) number(Person$email) as.character(Person) number(value(tutorial.Person$PhoneType, name="HOME")) }RProtoBuf/man/merge.Rd0000644000176200001440000000125313005133352014271 0ustar liggesusers\name{merge-methods} \alias{merge,Message,Message-method} \title{Merge two messages of the same type} \description{ Merge two \linkS4class{Message} objects of the same type. } \section{Methods}{ \describe{ \item{\code{signature(x = "Message", y = "Message")}}{ merge two messages of the same type } }} \section{Errors}{ An error of class "IncompatibleType" is thrown if the two messages are not of the same message type. } \keyword{methods} \examples{ m1 <- new( tutorial.Person, email = "francoisromain@free.fr" ) m2 <- new( tutorial.Person, id = 5 ) m3 <- merge( m1, m2 ) writeLines( as.character( m1 ) ) writeLines( as.character( m2 ) ) writeLines( as.character( m3 ) ) } RProtoBuf/man/ConnectionInputStream-methods.Rd0000644000176200001440000000073413005133352021131 0ustar liggesusers\name{ConnectionInputStream-methods} \docType{methods} \alias{ConnectionInputStream} \alias{ConnectionInputStream-methods} \alias{ConnectionInputStream,connection-method} \title{Creates an ConnectionInputStream} \description{ Constructor for \linkS4class{ConnectionInputStream} objects } \section{Methods}{ \describe{ \item{\code{signature(object="connection")}}{Creates a \linkS4class{ConnectionInputStream} reading from the given R binary connection.} }} \keyword{methods} RProtoBuf/man/ArrayInputStream-methods.Rd0000644000176200001440000000147313005133352020111 0ustar liggesusers\name{ArrayInputStream-methods} \docType{methods} \alias{ArrayInputStream} \alias{ArrayInputStream-methods} \alias{ArrayInputStream,raw,missing-method} \alias{ArrayInputStream,raw,integer-method} \alias{ArrayInputStream,raw,numeric-method} \title{Creates an ArrayInputStream} \description{ Constructor for \linkS4class{ArrayInputStream} objects } \section{Methods}{ \describe{ \item{\code{signature(payload = "raw", block_size = "missing" )}}{Creates a \linkS4class{ArrayInputStream} using the raw vector as the payload of the stream} \item{\code{signature(payload = "raw", block_size = "integer" )}}{Creates a \linkS4class{ArrayInputStream} ... same with block size. } \item{\code{signature(payload = "raw", block_size = "numeric" )}}{Creates a \linkS4class{ArrayInputStream} ... same with block size. } }} \keyword{methods} RProtoBuf/man/FileOutputStream-class.Rd0000644000176200001440000000352613005133352017556 0ustar liggesusers\name{FileOutputStream-class} \Rdversion{1.1} \docType{class} \alias{FileOutputStream-class} \alias{close,FileOutputStream-method} \alias{flush,FileOutputStream-method} \alias{GetErrno,FileOutputStream-method} \alias{SetCloseOnDelete,FileOutputStream-method} \title{Class "FileOutputStream" } \description{A \linkS4class{ZeroCopyOutputStream} reading from a file} \section{Objects from the Class}{ Objects can be created by the \link{FileOutputStream} function } \section{Slots}{ \describe{ \item{\code{pointer}:}{ External pointer to the \code{google::protobuf::io::FileOutputStream} C++ object} } } \section{Extends}{ Class \code{"\linkS4class{ZeroCopyOutputStream}"}, directly. } \section{Methods}{ \describe{ \item{close}{\code{signature(con="FileOutputStream")}: Flushes any buffers and closes the underlying file. Returns false if an error occurs during the process; use \code{GetErrno} to examine the error } \item{flush}{\code{signature(con="FileOutputStream")}: Flushes FileOutputStream's buffers but does not close the underlying file } \item{GetErrno}{\code{signature(object="FileInputStream")}: If an I/O error has occurred on this file descriptor, this is the errno from that error. Otherwise, this is zero. Once an error occurs, the stream is broken and all subsequent operations will fail. } \item{SetCloseOnDelete}{\code{signature(object="FileOutputStream")}: set the close on delete behavior. } } See \linkS4class{ZeroCopyOutputStream} for inherited methods } \references{ The \code{FileOutputStream} class from the protobuf C++ library. \url{http://code.google.com/apis/protocolbuffers/docs/reference/cpp/google.protobuf.io.zero_copy_stream_impl_lite.html#FileOutputStream} } \author{ Romain Francois } \seealso{ \linkS4class{ZeroCopyOutputStream} for methods } \keyword{classes} RProtoBuf/man/Next-methods.Rd0000644000176200001440000000040313005133352015545 0ustar liggesusers\name{Next-methods} \docType{methods} \alias{Next} \alias{Next-methods} \title{Obtains a chunk of data from the stream} \description{ Obtains a chunk of data from the stream } \seealso{ \linkS4class{ZeroCopyInputStream} implements Next. } \keyword{methods} RProtoBuf/man/serialize_pb.Rd0000644000176200001440000000262613005133352015647 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/serialize_pb.R \name{serialize_pb} \alias{can_serialize_pb} \alias{serialize_pb} \alias{unserialize_pb} \title{Serialize R object to Protocol Buffer Message.} \usage{ serialize_pb(object, connection, ...) } \arguments{ \item{object}{R object to serialize} \item{connection}{passed on to \code{\link{serialize}}} \item{...}{additional arguments passed on to \code{\link{serialize}}} } \description{ Serializes R objects to a general purpose protobuf message using the same \code{rexp.proto} descriptor and mapping between R objects and protobuf mesages as RHIPE. } \details{ Clients need both the message and the \code{rexp.proto} descriptor to parse serialized R objects. The latter is included in the the package installation \code{proto} directory: \code{system.file(package="RProtoBuf", "proto/rexp.proto")} The following storage types are natively supported by the descriptor: \code{character}, \code{raw}, \code{double}, \code{complex}, \code{integer}, \code{list}, and \code{NULL}. Objects with other storage types, such as functions, environments, S4 classes, etc, are serialized using base R \code{\link{serialize}} and stored in the proto \code{native} type. Missing values, attributes and numeric precision will be preserved. } \examples{ msg <- tempfile(); serialize_pb(iris, msg); obj <- unserialize_pb(msg); identical(iris, obj); } RProtoBuf/man/clone.Rd0000644000176200001440000000171013005133352014270 0ustar liggesusers\name{clone-methods} \docType{methods} \alias{clone} \alias{clone-methods} \alias{clone,Message-method} \title{Clone protocol buffer messages} \description{ Generic "clone" function and associated method for \linkS4class{Message} objects } \section{Methods}{ \describe{ \item{\code{signature(object = "Message")}}{ clone the message } }} \examples{ \dontrun{ # example proto file supplied with this package proto.file <- system.file( "proto", "addressbook.proto", package = "RProtoBuf" ) # reading a proto file and creating the descriptor Person <- P( "tutorial.Person", file = proto.file ) } \dontshow{Person <- P("tutorial.Person")} # creating a prototype message from the descriptor sheep <- new( Person, email = "francoisromain@free.fr", id = 2 ) # cloning the sheep newsheep <- clone( sheep ) # clone and update at once newsheep <- clone( sheep, id = 3 ) # this can also be used as a pseudo method sheep$clone() sheep$clone( id = 3 ) } \keyword{methods} RProtoBuf/man/bytesize.Rd0000644000176200001440000000112713005133352015030 0ustar liggesusers\name{bytesize-methods} \docType{methods} \alias{bytesize} \alias{bytesize-methods} \alias{bytesize,Message-method} \title{The number of bytes taken by a message } \description{ The number of bytes taken by a \linkS4class{Message} } \section{Methods}{ \describe{ \item{\code{signature(object = "Message")}}{ The number of bytes the message would take when serialized } }} \keyword{methods} \examples{ message <- new( tutorial.Person, name = "dddd", email = "eeeeeee", id = 1 ) bytesize( message ) \dontshow{ stopifnot( identical( bytesize(message), length(serialize(message, NULL ) ) ) ) } } RProtoBuf/man/name.Rd0000644000176200001440000000125313005133352014112 0ustar liggesusers\name{name} \docType{methods} \alias{name} \alias{name-methods} \alias{name,Descriptor-method} \alias{name,FieldDescriptor-method} \alias{name,EnumDescriptor-method} \alias{name,ServiceDescriptor-method} \alias{name,MethodDescriptor-method} \title{Name or full name of a descriptor} \description{ name or full name of a descriptor } \section{Methods}{ \describe{ \item{\code{signature(object = "Descriptor")}}{ ... } \item{\code{signature(object = "FieldDescriptor")}}{ ... } \item{\code{signature(object = "EnumDescriptor")}}{ ... } \item{\code{signature(object = "ServiceDescriptor")}}{ ... } \item{\code{signature(object = "MethodDescriptor")}}{ ... } }} \keyword{methods} RProtoBuf/man/SetCloseOnDelete-methods.Rd0000644000176200001440000000067213005133352020000 0ustar liggesusers\name{SetCloseOnDelete-methods} \docType{methods} \alias{SetCloseOnDelete} \alias{SetCloseOnDelete-methods} \title{set the close on delete behavior} \description{ By default, the file descriptor is not closed when a stream is destroyed, use \code{SetCloseOnDelete( stream, TRUE ) } to change that. } \section{Methods}{ See classes \linkS4class{FileInputStream} and \linkS4class{FileOutputStream} for implementations. } \keyword{methods} RProtoBuf/man/ArrayOutputStream-class.Rd0000644000176200001440000000170213005133352017747 0ustar liggesusers\name{ArrayOutputStream-class} \Rdversion{1.1} \docType{class} \alias{ArrayOutputStream-class} \title{Class "ArrayOutputStream" } \description{A \linkS4class{ZeroCopyOutputStream} backed by an in-memory array of bytes} \section{Objects from the Class}{ Objects can be created by the \link{ArrayOutputStream} function } \section{Slots}{ \describe{ \item{\code{pointer}:}{ External pointer to the \code{google::protobuf::io::ArrayOutputStream} C++ object} } } \section{Extends}{ Class \code{"\linkS4class{ZeroCopyOutputStream}"}, directly. } \section{Methods}{ See \linkS4class{ZeroCopyOutputStream} } \references{ The \code{ArrayOutputStream} class from the protobuf C++ library. \url{http://code.google.com/apis/protocolbuffers/docs/reference/cpp/google.protobuf.io.zero_copy_stream_impl_lite.html#ArrayOutputStream} } \author{ Romain Francois } \seealso{ \linkS4class{ZeroCopyOutputStream} for methods } \keyword{classes} RProtoBuf/man/containing_type-methods.Rd0000644000176200001440000000116213005133352020024 0ustar liggesusers\name{containing_type-methods} \alias{containing_type} \alias{containing_type-methods} \title{Gets the message type descriptor that contains a descriptor} \description{ Gets a \linkS4class{Descriptor} describing the message type that contains the descriptor. } \seealso{ The method is implemented for these classes : \linkS4class{Descriptor}, \linkS4class{EnumDescriptor}, \linkS4class{FieldDescriptor} } \examples{ # Containing type of a field is the message descriptor tutorial.Person$id$containing_type() # No containing type for the top-level message descriptor. tutorial.Person$containing_type() } \keyword{methods} RProtoBuf/man/size.Rd0000644000176200001440000000237013005133352014145 0ustar liggesusers\name{size-methods} \docType{methods} \alias{size} \alias{size-methods} \alias{size,Message-method} \title{Size of a message field} \description{ The number of object currently in a given field of a protocol buffer message. For non repeated fields, the size is 1 if the message has the field, 0 otherwise. For repeated fields, the size is the number of objects in the array. For repeated fields, the size can also be assigned to in order to shrink or grow the vector. Numeric types are given a default value of 0 when the new size is greater than the existing size. Character types are given a default value of "". Growing a repeated field in this way is not supported for message, group, and enum types. } \section{Methods}{ \describe{ \item{\code{signature(object = "Message")}}{Number of objects in a message field} }} \examples{ unitest.proto.file <- system.file("unitTests", "data", "unittest.proto", package = "RProtoBuf" ) readProtoFiles(file = unitest.proto.file) test <- new(protobuf_unittest.TestAllTypes) test$size("optional_int32") test$add("repeated_int32", 1:10) test$size("repeated_int32") test$repeated_int32 size(test, "repeated_int32") <- 5 test$repeated_int32 size(test, "repeated_int32") <- 15 test$repeated_int32 } \keyword{methods} RProtoBuf/man/Message-class.Rd0000644000176200001440000001334613005133352015667 0ustar liggesusers\name{Message-class} \Rdversion{1.1} \docType{class} \alias{Message-class} \alias{as.character,Message-method} \alias{$<-,Message-method} \alias{$,Message-method} \alias{[[,Message-method} \alias{[[<-,Message-method} \alias{serialize,Message-method} \alias{show,Message-method} \alias{update,Message-method} \alias{length,Message-method} \alias{names,Message-method} \alias{str,Message-method} \alias{toString,Message-method} \alias{identical,Message,Message-method} \alias{==,Message,Message-method} \alias{!=,Message,Message-method} \alias{all.equal,Message,Message-method} \alias{getExtension,Message-method} \alias{setExtension,Message-method} \alias{getExtension} \alias{setExtension} \title{Class "Message" } \description{ R representation of protocol buffer messages. This is a thin wrapper around the \code{Message} c++ class that holds the actual message as an external pointer. } \section{Objects from the Class}{ Objects are typically created by the \code{new} function invoked on a \linkS4class{Descriptor} object. } \section{Slots}{ \describe{ \item{\code{pointer}:}{external pointer to the c++ \code{Message} object} \item{\code{type}:}{fully qualified name of the message type} } } \section{Methods}{ \describe{ \item{as.character}{\code{signature(x = "Message")}: returns the debug string of the message. This is built from a call to the \code{DebugString} message of the \code{Message} object} \item{toString}{\code{signature(x = "Message")}: same as \code{as.character} } \item{$<-}{\code{signature(x = "Message")}: set the value of a field of the message. } \item{$}{\code{signature(x = "Message")}: gets the value of a field. Primitive types are brought back to R as R objects of the closest matching R type. Messages are brought back as instances of the \code{Message} class.} \item{[[}{\code{signature(x = "Message")}: extracts a field identified by its name or declared tag number } \item{[[<-}{\code{signature(x = "Message")}: replace the value of a field identified by its name or declared tag number } \item{serialize}{\code{signature(object = "Message")}: serialize a message. If the "connection" argument is \code{NULL}, the payload of the message is returned as a raw vector, if the "connection" argument is a binary writable connection, the payload is written into the connection. If "connection" is a character vector, the message is sent to the file (in binary format). } \item{show}{\code{signature(object = "Message")}: displays a short text about the message } \item{update}{\code{signature(object = "Message")}: set several fields of the message at once } \item{length}{\code{signature(x = "Message")}: The number of fields actually contained in the message. A field counts in these two situations: the field is repeated and the field size is greater than 0, the field is not repeated and the message has the field.} \item{setExtension}{\code{signature(object = "Message")}: set an extension field of the Message.} \item{getExtension}{\code{signature(object = "Message")}: get the value of an extension field of the Message.} \item{str}{\code{signature(object = "Message")}: displays the structure of the message } \item{identical}{\code{signature(x = "Message", y = "Message")}: Test if two messages are exactly identical } \item{==}{\code{signature(e1 = "Message", e2 = "Message")}: Same as \code{identical} } \item{!=}{\code{signature(e1 = "Message", e2 = "Message")}: Negation of \code{identical} } \item{all.equal}{\code{signature(e1 = "Message", e2 = "Message")}: Test near equality } \item{names}{\code{signature(x = "Message")}: extracts the names of the message. } } } \references{ The \code{Message} class from the C++ proto library. \url{http://code.google.com/apis/protocolbuffers/docs/reference/cpp/google.protobuf.message.html} } \author{ Romain Francois } \seealso{ \code{\link{P}} creates objects of class \linkS4class{Descriptor} that can be used to create messages. } \examples{ \dontrun{ # example proto file supplied with this package proto.file <- system.file( "proto", "addressbook.proto", package = "RProtoBuf" ) # reading a proto file and creating the descriptor Person <- P( "tutorial.Person", file = proto.file ) } \dontshow{ Person <- P("tutorial.Person") } PhoneNumber <- P( "tutorial.Person.PhoneNumber" ) # creating a prototype message from the descriptor p <- new( Person ) p$email # not set, returns default value p$id # not set, returns default value as.character( p ) # empty has( p, "email" ) # is the "email" field set has( p, "phone" ) # is the "email" field set length( p ) # number of fields actually set # update several fields at once romain <- update( new( Person ), email = "francoisromain@free.fr", id = 1, name = "Romain Francois", phone = new( PhoneNumber , number = "+33(0)...", type = "MOBILE" ) ) # supply parameters to the constructor dirk <- new( Person, email = "edd@debian.org", id = 2, name = "Dirk Eddelbuettel" ) # update the phone repeated field with a list of PhoneNumber messages dirk$phone <- list( new( PhoneNumber , number = "+01...", type = "MOBILE" ), new( PhoneNumber , number = "+01...", type = "HOME" ) ) # with/within style saptarshi <- within( new(Person), { id <- 3 name <- "Saptarshi Guha" email <- "saptarshi.guha@gmail.com" } ) # make an addressbook book <- new( tutorial.AddressBook, person = list( romain, dirk, saptarshi ) ) # serialize the message to a file tf <- tempfile( ) serialize( book, tf ) # the payload of the message serialize( book, NULL ) # read the file into a new message m <- tutorial.AddressBook$read( tf ) writeLines( as.character( m ) ) sapply( m$person, function(p) p$name ) } \keyword{classes} RProtoBuf/man/field.Rd0000644000176200001440000000042713005133352014257 0ustar liggesusers\name{field-methods} \alias{field} \alias{field-methods} \title{Extract a field descriptor} \description{ Extract a \linkS4class{FieldDescriptor} from a \linkS4class{Descriptor} } \seealso{ The method is implemented for the \linkS4class{Descriptor} class } \keyword{methods} RProtoBuf/man/ConnectionOutputStream-class.Rd0000644000176200001440000000146413005133352020775 0ustar liggesusers\name{ConnectionOutputStream-class} \Rdversion{1.1} \docType{class} \alias{ConnectionOutputStream-class} \title{Class "ConnectionOutputStream" } \description{A \linkS4class{ZeroCopyOutputStream} writing to a binary R connection} \section{Objects from the Class}{ Objects can be created by the \link{ConnectionOutputStream} function } \section{Slots}{ \describe{ \item{\code{pointer}:}{ External pointer to the \code{rprotobuf::ConnectionOutputStream} C++ object} } } \section{Extends}{ Class \code{"\linkS4class{ZeroCopyOutputStream}"}, directly. } \section{Methods}{ See \linkS4class{ZeroCopyOutputStream} } \references{ The internal C++ class \code{ConnectionOutputStream} } \author{ Romain Francois } \seealso{ \linkS4class{ZeroCopyOutputStream} for methods } \keyword{classes} RProtoBuf/man/RProtoBuf-package.Rd0000644000176200001440000000206113005133352016443 0ustar liggesusers\name{RProtoBuf-package} \alias{RProtoBuf-package} \alias{RProtoBuf} \docType{package} \title{R Interface to the Protocol Buffers API} \description{ Protocol Buffers are a way of encoding structured data in an efficient yet extensible format. Google uses Protocol Buffers for almost all of its internal RPC protocols and file formats. This package provides R API to create, manipulate, parse and serialize protocol buffer messages from R } \author{Romain Francois, Dirk Eddelbuettel, Murray Stokely and Jeroen Ooms.} \references{\url{https://github.com/eddelbuettel/rprotobuf}} \keyword{package} \seealso{\linkS4class{Message} for some examples} \examples{ \dontrun{ # an example proto file system.file( "proto", "addressbook.proto", package = "RProtoBuf" ) # create a message of type AddressBook, defined in the example proto file demo( "addressbook", package = "RProtoBuf" ) # using R binary connections and files to read and write messages demo( "io", package = "RProtoBuf" ) # more documentation in the vignette vignette( "RProtoBuf", package = "RProtoBuf" ) } } RProtoBuf/man/aslist.Rd0000644000176200001440000000272013005133352014471 0ustar liggesusers\name{as.list.Message} \alias{as.list.Message} \alias{as.list.Descriptor} \alias{as.list.EnumDescriptor} \alias{as.list.FileDescriptor} \alias{as.list.ServiceDescriptor} \title{ Grab the protocol buffer message as an R list } \description{ Utility to grab the protocol buffer message as an R list, with one item per field. } \usage{ \S3method{as.list}{Message}(x, ...) \S3method{as.list}{Descriptor}(x, ...) \S3method{as.list}{EnumDescriptor}(x, ...) \S3method{as.list}{FileDescriptor}(x, ...) \S3method{as.list}{ServiceDescriptor}(x, ...) } \arguments{ \item{x}{A protocol buffer message, instance of \linkS4class{Message}, or a protocol message descriptor, instance of \linkS4class{Descriptor} } \item{\dots}{ignored} } \value{ For messages, a list of the content of the fields is returned. For message type descriptors, a list containing nested type descriptors (\linkS4class{Descriptor} objects), enum type descriptors (\linkS4class{EnumDescriptor} objects), then field descriptors (\linkS4class{FieldDescriptor} objects) in that order. For enum descriptors, a named list of the enumerated values. For file descriptors, a named list of descriptors defined in the specified file descriptor. For service descriptors, ... } \author{ Romain Francois } \examples{ Person <- P( "tutorial.Person" ) romain <- new( Person, email = "francoisromain@free.fr", id = 1 ) as.list( romain ) as.list( Person ) as.list( Person$PhoneType) } \keyword{ programming } RProtoBuf/man/clear.Rd0000644000176200001440000000271113005133352014260 0ustar liggesusers\name{clear-methods} \docType{methods} \alias{clear} \alias{clear-methods} \alias{clear,Message,character-method} \alias{clear,Message,integer-method} \alias{clear,Message,missing-method} \alias{clear,Message,numeric-method} \alias{clear,Message,raw-method} \title{Clear a field or all fields of the message and set them to their default values} \description{ Clear one field or all fields of the message and set them to their default values } \section{Methods}{ \describe{ \item{\code{signature(object = "Message", field = "missing")}}{Clear all fields of the message and set them to their default values } \item{\code{signature(object = "Message", field = "character")}}{ Clear the field identified by its name } \item{\code{signature(object = "Message", field = "integer")}}{ Clear the field identified by its tag number } \item{\code{signature(object = "Message", field = "numeric")}}{ Clear the field identified by its tag number } \item{\code{signature(object = "Message", field = "raw")}}{ Clear the field identified by its tag number} }} \keyword{methods} \examples{ message <- new( tutorial.Person, name = "dddd", email = "eeeeeee", id = 1 ) writeLines( as.character( message ) ) clear( message ) # clear works also as a pseudo method : message$clear() writeLines( as.character( message ) ) # clear single fields message <- new( tutorial.Person, name = "dddd", email = "eeeeeee", id = 1 ) message$clear( "name" ) writeLines( as.character( message ) ) } RProtoBuf/man/GetErrno-methods.Rd0000644000176200001440000000057013005133352016361 0ustar liggesusers\name{GetErrno-methods} \docType{methods} \alias{GetErrno} \alias{GetErrno-methods} \title{Get the error number for an I/O error} \description{ If an I/O error has occurred on this file descriptor, this is the errno from that error } \section{Methods}{ See classes \linkS4class{FileInputStream} and \linkS4class{FileOutputStream} for implementations. } \keyword{methods} RProtoBuf/man/with.Rd0000644000176200001440000000233213005133352014144 0ustar liggesusers\name{with.Message} \alias{with.Message} \alias{within.Message} \title{ with and within methods for protocol buffer messages } \description{ Convenience wrapper that allow getting and setting fields of protocol buffer messages from within the object } \usage{ \S3method{with}{Message}(data, expr, ...) \S3method{within}{Message}(data, expr, ...) } \arguments{ \item{data}{A protocol buffer message, instance of \linkS4class{Message} } \item{expr}{R expression to evaluate} \item{\dots}{ignored} } \details{ The expression is evaluated in an environment that allows to set and get fields of the message The fields of the message are mapped to active bindings (see \link{makeActiveBinding}) so that they can be accessed and modified from within the environment. } \value{ \code{with} returns the value of the expression and \code{within} returns the \code{data} argument. } \author{ Romain Francois } \examples{ \dontrun{ proto.file <- system.file( "proto", "addressbook.proto", package = "RProtoBuf" ) Person <- P( "tutorial.Person", file = proto.file ) } \dontshow{Person <- P( "tutorial.Person") } romain <- within( new( Person ), { email <- "francoisromain@free.fr" id <- 10L } ) } \keyword{ classes } RProtoBuf/man/label.Rd0000644000176200001440000000153613005133352014255 0ustar liggesusers\name{label-methods} \alias{label} \alias{label-methods} \alias{LABEL_OPTIONAL} \alias{LABEL_REQUIRED} \alias{LABEL_REPEATED} \title{Gets the label of a field} \description{ Gets the label of a field (optional, required, or repeated). } \arguments{ \item{object}{A \linkS4class{FieldDescriptor} object.} \item{as.string}{If true, print a string representation of the type.} } \seealso{ The method is implemented for the \linkS4class{FieldDescriptor} class } \keyword{methods} \examples{ \dontrun{ proto.file <- system.file( "proto", "addressbook.proto", package = "RProtoBuf" ) Person <- P( "tutorial.Person", file = proto.file ) } \dontshow{ Person <- P("tutorial.Person") } label(Person$id) label(Person$email) label(Person$phone) label(Person$id, TRUE) label(Person$email, TRUE) label(Person$phone, TRUE) LABEL_OPTIONAL LABEL_REQUIRED LABEL_REPEATED }RProtoBuf/man/read.Rd0000644000176200001440000000272413005133352014111 0ustar liggesusers\name{read-methods} \docType{methods} \alias{read} \alias{read-methods} \alias{read,Descriptor,character-method} \alias{read,Descriptor,raw-method} \alias{read,Descriptor,ANY-method} \title{Read a protocol buffer message from a connection} \description{ Read a \linkS4class{Message} from a connection using its associated \linkS4class{Descriptor} } \section{Methods}{ \describe{ \item{\code{signature(descriptor = "Descriptor", input = "character")}}{ Read the message from a file } \item{\code{signature(descriptor = "Descriptor")}}{ Read from a binary connection. } \item{\code{signature(descriptor = "Descriptor", input = "raw")}}{ Read the message from a raw vector } }} \keyword{methods} \examples{ # example file that contains a "tutorial.AddressBook" message book <- system.file( "examples", "addressbook.pb", package = "RProtoBuf" ) # read the message message <- read( tutorial.AddressBook, book ) # or using the pseudo method message <- tutorial.AddressBook$read( book ) # write its debug string writeLines( as.character( message ) ) # grab the name of each person sapply( message$person, function(p) p$name ) # read from a binary file connection f <- file( book, open = "rb" ) message2 <- read( tutorial.AddressBook, f ) close( f ) # read from a message payload (raw vector) payload <- readBin( book, raw(0), 5000 ) message3 <- tutorial.AddressBook$read( payload ) \dontshow{ stopifnot( identical( message, message2) ) stopifnot( identical( message, message3) ) } } RProtoBuf/man/isInitialized.Rd0000644000176200001440000000131613005133352015773 0ustar liggesusers\name{isInitialized-methods} \docType{methods} \alias{isInitialized} \alias{isInitialized-methods} \alias{isInitialized,Message-method} \title{Indicates if a protocol buffer message is initialized} \description{ Indicates if a \linkS4class{Message} is initialized. A message is initialized if all its required fields are set. } \section{Methods}{ \describe{ \item{\code{ signature(object = "Message")}}{ is the message initialized} }} \examples{ message <- new( tutorial.Person, name = "" ) isInitialized( message ) # FALSE (id is not set) message$isInitialized() # FALSE message <- new( tutorial.Person, name = "", id = 2 ) isInitialized( message ) # TRUE message$isInitialized() # TRUE } \keyword{methods} RProtoBuf/man/EnumValueDescriptor-class.Rd0000644000176200001440000000521613005133352020240 0ustar liggesusers\name{EnumValueDescriptor-class} \Rdversion{1.1} \docType{class} \alias{EnumValueDescriptor-class} \alias{show,EnumValueDescriptor-method} \alias{as.character,EnumValueDescriptor-method} \alias{toString,EnumValueDescriptor-method} \alias{$,EnumValueDescriptor-method} \alias{name,EnumValueDescriptor-method} \alias{number,EnumValueDescriptor-method} \alias{enum_type,EnumValueDescriptor,missing,missing-method} \title{Class "EnumValueDescriptor" } \description{ R representation of an enum value descriptor. This is a thin wrapper around the \code{EnumValueDescriptor} c++ class. } \section{Objects from the Class}{ Objects of this class are typically retrieved with the \code{value} method of the \linkS4class{EnumDescriptor} class } \section{Slots}{ \describe{ \item{\code{pointer}:}{external pointer to the \code{EnumValueDescriptor} instance} \item{\code{name}:}{ simple name of the enum } \item{\code{full_name}:}{fully qualified name } } } \section{Methods}{ \describe{ \item{show}{\code{signature(object = "EnumValueDescriptor")}: small information } \item{as.character}{\code{signature(x = "EnumValueDescriptor")}: returns the debug string of the enum descriptor. This is retrieved by a call to the \code{DebugString} method of the EnumDescriptor object. } \item{toString}{\code{signature(x = "EnumValueDescriptor")}: same as \code{as.character} } \item{$}{\code{signature(x = "EnumValueDescriptor")}: invoke pseudo methods } \item{name}{\code{signature(object = "EnumValueDescriptor", full = "logical")}: return the name of this enum constant.} \item{number}{\code{signature(object = "EnumValueDescriptor")}: return the numeric value of this enum constant.} \item{enum_type}{\code{signature(object = "EnumDescriptor")} : retrieves the \linkS4class{EnumDescriptor} related to this value descriptor.} } } \references{ The \code{EnumValueDescriptor} C++ class. \url{http://code.google.com/apis/protocolbuffers/docs/reference/cpp/google.protobuf.descriptor.html#EnumValueDescriptor} } \author{ Romain Francois } \examples{ \dontrun{ # example proto file supplied with this package proto.file <- system.file( "proto", "addressbook.proto", package = "RProtoBuf" ) # reading a proto file and creating the descriptor Person <- P( "tutorial.Person", file = proto.file ) } \dontshow{Person <- P( "tutorial.Person" ) } # enum type Person$PhoneType # enum value type value(Person$PhoneType, 1) name(value(Person$PhoneType, 1)) name(value(Person$PhoneType, 1), TRUE) number(value(Person$PhoneType, number=1)) enum_type(value(Person$PhoneType, number=1)) } \keyword{classes} RProtoBuf/man/invokeLocally.Rd0000644000176200001440000000107413005133352016006 0ustar liggesusers\name{invoke-methods} \docType{methods} \alias{invoke} \alias{invoke-methods} \alias{invoke,MethodDescriptor,Message,missing-method} \alias{invoke,MethodDescriptor,Message,RpcHTTP-method} \title{invoke a protobuf rpc method} \description{ invoke a protobuf rpc method } \section{Methods}{ \describe{ \item{\code{signature(method = "MethodDescriptor", message = "Message")}}{invoke a protobuf rpc method locally.} \item{\code{signature(method = "MethodDescriptor", message = "Message", protocol = "RpcHTTP" )}}{invoke a protobuf rpc method over http.} }} \keyword{methods} RProtoBuf/man/Descriptor-class.Rd0000644000176200001440000001216413005133352016416 0ustar liggesusers\name{Descriptor-class} \Rdversion{1.1} \docType{class} \alias{Descriptor-class} \alias{as.character,Descriptor-method} \alias{$<-,Descriptor-method} \alias{$,Descriptor-method} \alias{new,Descriptor-method} \alias{show,Descriptor-method} \alias{toString,Descriptor-method} \alias{containing_type,Descriptor-method} \alias{field_count,Descriptor-method} \alias{nested_type_count,Descriptor-method} \alias{enum_type_count,Descriptor-method} \alias{field,Descriptor-method} \alias{nested_type,Descriptor-method} \alias{enum_type,Descriptor,ANY,ANY-method} \alias{[[,Descriptor-method} \alias{names,Descriptor-method} \alias{length,Descriptor-method} \title{Class "Descriptor" } \description{ full descriptive information about a protocol buffer message type. This is a thin wrapper around the C++ class \code{Descriptor}} \section{Objects from the Class}{ Objects are usually created by calls to the \code{\link{P}} function. } \section{Slots}{ \describe{ \item{\code{pointer}:}{external pointer holding a \code{Descriptor} object } \item{\code{type}:}{full name of the corresponding message type} } } \section{Methods}{ \describe{ \item{as.character}{\code{signature(x = "Descriptor")}: returns the debug string of the descriptor. This is retrieved by a call to the \code{DebugString} method of the Descriptor object. } \item{toString}{\code{signature(x = "Descriptor")}: same as \code{as.character} } \item{$}{\code{signature(x = "Descriptor")}: retrieves a descriptor for a member of the message type. This can either be another "Descriptor" instance describing a nested type, or a \linkS4class{EnumDescriptor} object describing an enum type, or a \linkS4class{FieldDescriptor} object describing a field of the message} \item{new}{\code{signature(Class = "Descriptor")}: creates a prototype message (\linkS4class{Message}) of this descriptor} \item{show}{\code{signature(object = "Descriptor")}: simple information} \item{containing_type}{\code{signature(object = "Descriptor")} : returns a descriptor of the message type that contains this message descriptor, or \code{NULL} if this is a top-level message type.} \item{field_count}{\code{signature(object = "Descriptor")} : The number of fields of this message type. } \item{nested_type_count}{\code{signature(object = "Descriptor")} : The number of nested types of this message type. } \item{enum_type_count}{\code{signature(object = "Descriptor")} : The number of enum types of this message type. } \item{field}{\code{signature(object = "Descriptor")} : extract a field descriptor from a descriptor. Exactly one argument of \code{index}, \code{number} or \code{name} has to be used. If \code{index} is used, the field descriptor is retrieved by position, using the \code{field} method of the \code{google::protobuf::Descriptor} C++ class. If \code{number} is used, the field descriptor is retrieved using the tag number, with the \code{FindFieldByNumber} C++ method. If \code{name} is used, the field descriptor is retrieved by name using the \code{FindFieldByName} } \item{nested_type}{\code{signature(object = "Descriptor")} : extracts a message type descriptor that is nested in this descriptor. Exactly one argument of \code{index} of \code{name} has to be used. If \code{index} is used, the nested type will be retrieved using its position with the \code{nested_type} method of the \code{google::protobuf::Descriptor} C++ class. If \code{name} is used, the nested type will be retrieved using its name, with the \code{FindNestedTypeByName} C++ method } \item{enum_type}{\code{signature(object = "Descriptor")} : extracts an enum type descriptor that is contained in this descriptor. Exactly one argument of \code{index} of \code{name} has to be used. If \code{index} is used, the enum type will be retrieved using its position with the \code{enum_type} method of the \code{google::protobuf::Descriptor} C++ class. If \code{name} is used, the enum type will be retrieved using its name, with the \code{FindEnumTypeByName} C++ method } \item{[[}{\code{signature(x = "Descriptor")}: extracts a field identified by its name or declared tag number} \item{names}{\code{signature(x = "Descriptor")} : extracts names of this descriptor} \item{length}{\code{signature(x = "Descriptor")} : extracts length of this descriptor} } } \references{ The \code{Descriptor} c++ class. \url{http://code.google.com/apis/protocolbuffers/docs/reference/cpp/google.protobuf.descriptor.html#Descriptor} } \author{ Romain Francois } \seealso{ the \code{\link{P}} function creates "Descriptor" messages. } \examples{ \dontrun{ # example proto file supplied with this package proto.file <- system.file( "proto", "addressbook.proto", package = "RProtoBuf" ) # reading a proto file and creating the descriptor Person <- P( "tutorial.Person", file = proto.file ) } \dontshow{Person <- P( "tutorial.Person" ) } # enum type Person$PhoneType # nested type Person$PhoneNumber # field Person$email # use this descriptor to create a message new( Person ) } \keyword{classes} RProtoBuf/man/readASCII.Rd0000644000176200001440000000231113005133352014652 0ustar liggesusers\name{readASCII-methods} \docType{methods} \alias{readASCII} \alias{readASCII-methods} \alias{readASCII,Descriptor,ANY-method} \alias{readASCII,Descriptor,character-method} \title{read a message in ASCII format} \description{ Method to read a Message in ASCII format } \section{Methods}{ \describe{ \item{\code{signature(descriptor = "Descriptor", input = "ANY")}}{ Read the message from a connection (file, etc ...) } \item{\code{signature(descriptor = "Descriptor", input = "character")}}{ Read the message directly from the character string } }} \keyword{methods} \examples{ # example file that contains a "tutorial.AddressBook" message book <- system.file( "examples", "addressbook.pb", package = "RProtoBuf" ) # read the message message <- read( tutorial.AddressBook, book ) # Output in text format to a temporary file out.file <- tempfile() writeLines( as.character(message), file(out.file)) # Verify that we can read back in the message from a text file. message2 <- readASCII( tutorial.AddressBook, file(out.file, "rb")) # Verify that we can read back in the message from an unopened file. message3 <- readASCII( tutorial.AddressBook, file(out.file)) \dontshow{ stopifnot( identical( message, message2) ) } } RProtoBuf/man/ZeroCopyInputStream-class.Rd0000644000176200001440000000666613005133352020260 0ustar liggesusers\name{ZeroCopyInputStream-class} \Rdversion{1.1} \docType{class} \alias{ZeroCopyInputStream-class} \alias{Skip,ZeroCopyInputStream-method} \alias{ByteCount,ZeroCopyInputStream-method} \alias{BackUp,ZeroCopyInputStream-method} \alias{Next,ZeroCopyInputStream,missing-method} \alias{$,ZeroCopyInputStream-method} \alias{ReadRaw} \alias{ReadRaw-methods} \alias{ReadRaw,ZeroCopyInputStream,integer-method} \alias{ReadRaw,ZeroCopyInputStream,numeric-method} \alias{ReadString} \alias{ReadString-methods} \alias{ReadString,ZeroCopyInputStream,integer-method} \alias{ReadString,ZeroCopyInputStream,numeric-method} \alias{ReadVarint32} \alias{ReadVarint32-methods} \alias{ReadVarint32,ZeroCopyInputStream-method} \alias{ReadLittleEndian32} \alias{ReadLittleEndian32-methods} \alias{ReadLittleEndian32,ZeroCopyInputStream-method} \alias{ReadLittleEndian64} \alias{ReadLittleEndian64-methods} \alias{ReadLittleEndian64,ZeroCopyInputStream-method} \alias{ReadVarint64} \alias{ReadVarint64-methods} \alias{ReadVarint64,ZeroCopyInputStream-method} \title{Virtual Class "ZeroCopyInputStream" } \description{R wrapper for the ZeroCopyInputStream c++ class} \section{Objects from the Class}{ This is a virtual class } \section{Slots}{ \describe{ \item{\code{pointer}:}{external pointer to the \code{google::protobuf::io::ZeroCopyInputStream} object} } } \section{Methods}{ \describe{ \item{$}{\code{signature(x="ZeroCopyInputStream")}: invokes a method} \item{Next}{\code{signature(object="ZeroCopyInputStream")}: Get a number of bytes from the stream as a raw vector. } \item{Skip}{\code{signature(object="ZeroCopyInputStream")}: skip a number of bytes} \item{BackUp}{\code{signature(object="ZeroCopyInputStream")}: Backs up a number of bytes, so that the next call to \code{Next} returns data again that was already returned by the last call to \code{Next}.} \item{ByteCount}{\code{signature(object="ZeroCopyInputStream")}: Returns the total number of bytes read since this object was created. } \item{ReadRaw}{\code{signature(object="ZeroCopyInputStream", size = "integer")}: read raw bytes from the stream} \item{ReadRaw}{\code{signature(object="ZeroCopyInputStream", size = "numeric")}: read raw bytes from the stream} \item{ReadString}{\code{signature(object="ZeroCopyInputStream", size = "integer")}: same as \code{ReadRaw} but formats the result as a string} \item{ReadString}{\code{signature(object="ZeroCopyInputStream", size = "numeric")}: same as \code{ReadRaw} but formats the result as a string} \item{ReadVarint32}{\code{signature(object="ZeroCopyInputStream")}: Read an unsigned integer with Varint encoding, truncating to 32 bits. } \item{ReadLittleEndian32}{\code{signature(object="ZeroCopyInputStream")}: Read a 32-bit little-endian integer. } \item{ReadLittleEndian64}{\code{signature(object="ZeroCopyInputStream")}: Read a 64-bit little-endian integer. In R the value is stored as a \code{double} which looses some precision (no other way) } \item{ReadVarint64}{\code{signature(object="ZeroCopyInputStream")}: Read a 64-bit integer with varint encoding. In R the value is stored as a \code{double} which looses some precision (no other way) } } } \author{ Romain Francois } \references{ The \code{google::protobuf::io::ZeroCopyInputStream} C++ class. \url{http://code.google.com/apis/protocolbuffers/docs/reference/cpp/google.protobuf.io.zero_copy_stream.html#ZeroCopyInputStream} } \seealso{ TODO: add classes that extend } \keyword{classes} RProtoBuf/man/fetch.Rd0000644000176200001440000000053413005133352014264 0ustar liggesusers\name{fetch-methods} \docType{methods} \alias{fetch} \alias{fetch-methods} \alias{fetch,Message-method} \title{Fetch content of a repeated field} \description{ Fetch content of a repeated field of a message } \section{Methods}{ \describe{ \item{\code{signature(object = "Message")}}{Fetch content of a message repeated field} }} \keyword{methods} RProtoBuf/man/enum_type_count.Rd0000644000176200001440000000040113005133352016401 0ustar liggesusers\name{enum_type_count-methods} \alias{enum_type_count} \alias{enum_type_count-methods} \title{The number of enum types} \description{ The number of enum types } \seealso{ The method is implemented for the \linkS4class{Descriptor} class } \keyword{methods} RProtoBuf/man/readProtoFiles.Rd0000644000176200001440000000225113005133352016113 0ustar liggesusers\name{readProtoFiles} \alias{readProtoFiles} \title{ protocol buffer descriptor importer } \description{ Imports proto files into the descriptor pool that is then used by the \code{P} function to resolve message type names. } \usage{ readProtoFiles(files, dir, package="RProtoBuf", pattern="\\\\.proto$", lib.loc=NULL) } \arguments{ \item{files}{Proto files} \item{dir}{Directory. If \code{files} is not specified, files with the "proto" extension in the \code{dir} directory are imported} \item{package}{R package name. If \code{files} and \code{dir} are missing, "proto" files in the "proto" directory of the package tree are imported.} \item{pattern}{A filename pattern to match proto files.} \item{lib.loc}{Library location.} } \value{ \code{NULL}, invisibly. } \author{ Romain Francois } \seealso{ \code{\link{P}} } \examples{ \dontrun{ # from a package readProtoFiles( package = "RProtoBuf" ) # from a directory proto.dir <- system.file( "proto", package = "RProtoBuf" ) readProtoFiles( dir = proto.dir ) # set of files proto.files <- list.files( proto.dir, full.names = TRUE ) readProtoFiles( proto.files ) } } \keyword{ programming } RProtoBuf/man/nested_type_count.Rd0000644000176200001440000000040013005133352016716 0ustar liggesusers\name{nested_type_count-methods} \alias{nested_type_count} \alias{nested_type_count-methods} \title{The number of fields} \description{ The number of fields } \seealso{ The method is implemented for the \linkS4class{Descriptor} class } \keyword{methods} RProtoBuf/configure.win0000644000176200001440000000000013005133352014615 0ustar liggesusersRProtoBuf/cleanup0000755000176200001440000000072613164671424013526 0ustar liggesusers#!/bin/sh rm -f config.* src/Makedeps src/Makevars \ src/addressbook.pb.cc src/addressbook.pb.h \ src/protobufrpc.pb.cc src/protobufrpc.pb.h \ src/*.o src/*.d src/*.a src/*.dll src/*.so src/*.rc */*~ *~ \ src/symbols.rds \ vignettes/RProtoBuf*.aux vignettes/RProtoBuf*.log \ vignettes/RProtoBuf*.out vignettes/RProtoBuf*.toc \ vignettes/RProtoBuf*.tex vignettes/RProtoBuf*.pdf \ vignettes/pinp.cls rm -rf inst/doc/auto autom4te.cache RProtoBuf/tools/0000755000176200001440000000000013037255745013307 5ustar liggesusersRProtoBuf/tools/winlibs.R0000644000176200001440000000070013037255745015076 0ustar liggesusers# Build against protobuf libs compiled with Rtools # by Jeroen Ooms. Last updated: August 2016 if (!file.exists("../windows/protobuf-3.0.0/include/google/protobuf/descriptor.h")) { if (getRversion() < "3.3.0") setInternet2() download.file("https://github.com/rwinlib/protobuf/archive/v3.0.0.zip", "lib.zip", quiet = TRUE) dir.create("../windows", showWarnings = FALSE) unzip("lib.zip", exdir = "../windows") unlink("lib.zip") } RProtoBuf/.Rinstignore0000644000176200001440000000002213005133352014425 0ustar liggesusersinst/doc/Makefile