ConstantsConstants are fixed values that are used in the whole database code.
SUFFIX_OLD_DATABASE_FILE = ".data.db"The file name suffix of a H2 version 1.1 database file.
SUFFIX_DB_FILE = ".db"The file name suffix of all database files.
SUFFIX_PAGE_FILE = ".h2.db"The file name suffix of page files.
SERVER_PROPERTIES_NAME = ".h2.server.properties"The name of the server properties file for the H2 Console.
SUFFIX_LOB_FILE = ".lob.db"The file name suffix of large object files.
SUFFIX_LOBS_DIRECTORY = ".lobs.db"The suffix of the directory name used if LOB objects are stored in a
directory.
SUFFIX_LOCK_FILE = ".lock.db"The file name suffix of file lock files that are used to make sure a
database is open by only one process at any time.
SUFFIX_MV_FILE = ".mv.db"The file name suffix of a MVStore file.
SUFFIX_MV_STORE_NEW_FILE = ".newFile"The file name suffix of a new MVStore file, used when compacting a store.
SUFFIX_TEMP_FILE = ".temp.db"The file name suffix of temporary files.
SUFFIX_MV_STORE_TEMP_FILE = ".tempFile"The file name suffix of a temporary MVStore file, used when compacting a
store.
SUFFIX_TRACE_FILE = ".trace.db"The file name suffix of trace files.
VERSION_STABLE = "1.4.199"The last stable version name.
BUILD_DATE_STABLE = "2019-03-13"The build date of the last stable release.
BUILD_DATE = "2019-10-14"The build date is updated for each public release.
PG_VERSION = "8.2.23"Announced version for PgServer.
PREFIX_INDEX = "INDEX_"The name prefix used for indexes that are not explicitly named.
CACHE_TYPE_DEFAULT = "LRU"The default cache type.
PREFIX_PRIMARY_KEY = "PRIMARY_KEY_"The name prefix used for primary key constraints that are not explicitly
named.
PUBLIC_ROLE_NAME = "PUBLIC"Every user belongs to this role.
SCHEMA_MAIN = "PUBLIC"The name of the default schema.
PREFIX_QUERY_ALIAS = "QUERY_ALIAS_"The name prefix used for query aliases that are not explicitly named.
PREFIX_JOIN = "SYSTEM_JOIN_"The name prefix used for synthetic nested join tables.
CLUSTERING_ENABLED = "TRUE"The value of the cluster setting if clustering is enabled (the actual
value is checked later).
CLUSTERING_DISABLED = "\'\'"The value of the cluster setting if clustering is disabled.
CONN_URL_COLUMNLIST = "jdbc:columnlist:connection"The database URL used when calling a function if only the column list
should be returned.
CONN_URL_INTERNAL = "jdbc:default:connection"The database URL used when calling a function if the data should be
returned.
START_URL = "jdbc:h2:"The database URL prefix of this database.
URL_FORMAT = "jdbc:h2:{ {.|mem:}[name] | [file:]fileName | {tcp|ssl}:[//]server[:port][,server2[:port]]/name }[;key=value...]"The database URL format in simplified Backus-Naur form.
USER_PACKAGE = "org.h2.dynamic"The package name of user defined classes.
SERVER_PROPERTIES_DIR = "~"The default directory name of the server properties file for the H2
Console.
INFORMATION_SCHEMA_ID = -1The identity of INFORMATION_SCHEMA.
ALLOW_LITERALS_NONE = 0Constant meaning no literals are allowed in SQL statements.
LOCK_MODE_OFF = 0The lock mode that means no locking is used at all.
MAIN_SCHEMA_ID = 0The identity of PUBLIC schema.
ALLOW_LITERALS_NUMBERS = 1Constant meaning only numbers are allowed in SQL statements (but no
texts).
LOCK_MODE_TABLE = 1The lock mode that means table level locking is used for reads and
writes.
VERSION_MAJOR = 1The major version of this database.
TCP_PROTOCOL_VERSION_10 = 10The TCP protocol version number 10.
DEADLOCK_CHECK = 100The number of milliseconds after which to check for a deadlock if locking
is not successful.
QUERY_STATISTICS_MAX_ENTRIES = 100The maximum number of entries in query statistics.
COST_ROW_OFFSET = 1000The cost is calculated on rowcount + this offset,
to avoid using the wrong or no index if the table
contains no rows _currently_ (when preparing the statement)
LOCK_SLEEP = 1000The number of milliseconds to wait between checking the .lock.db file
still exists once a database is locked.
SELECTIVITY_DISTINCT_COUNT = 10000The number of distinct values to keep in memory when running ANALYZE.
VIEW_COST_CACHE_MAX_AGE = 10000The maximum time in milliseconds to keep the cost of a view.
10000 means 10 seconds.
DEFAULT_MAX_OPERATION_MEMORY = 100000The default for the setting MAX_OPERATION_MEMORY.
MAX_PARAMETER_INDEX = 100000The highest possible parameter index.
DEFAULT_RESULT_SET_CONCURRENCY = 1007The default result set concurrency for statements created with
Connection.createStatement() or prepareStatement(String sql).
SLOW_QUERY_LIMIT_MS = 100LQueries that take longer than this number of milliseconds are written to
the trace file with the level info.
ENCRYPTION_KEY_HASH_ITERATIONS = 1024The password is hashed this many times
to slow down dictionary attacks.
UNDO_BLOCK_SIZE = 1048576The maximum size of an undo log block.
TCP_PROTOCOL_VERSION_11 = 11The TCP protocol version number 11.
TCP_PROTOCOL_VERSION_12 = 12The TCP protocol version number 12.
MEMORY_PAGE_DATA_OVERFLOW = 120The memory needed by an object of class PageDataOverflow.
TCP_PROTOCOL_VERSION_13 = 13The TCP protocol version number 13.
IO_BUFFER_SIZE_COMPRESS = 131072The block size used to compress data in the LZFOutputStream.
TCP_PROTOCOL_VERSION_14 = 14The TCP protocol version number 14.
TCP_PROTOCOL_VERSION_15 = 15The TCP protocol version number 15.
CACHE_MIN_RECORDS = 16The minimum number of entries to keep in the cache.
FILE_BLOCK_SIZE = 16The block of a file. It is also the encryption block size.
TCP_PROTOCOL_VERSION_16 = 16The TCP protocol version number 16.
DEFAULT_MAX_LOG_SIZE = 16777216LThe default value for the maximum transaction log size.
TCP_PROTOCOL_VERSION_17 = 17The TCP protocol version number 17.
TCP_PROTOCOL_VERSION_18 = 18The TCP protocol version number 18.
MEMORY_PAGE_BTREE = 184The memory needed by an object of class PageBtree.
TCP_PROTOCOL_VERSION_19 = 19The TCP protocol version number 19.
TCP_PROTOCOL_VERSION_MAX_SUPPORTED = 19Maximum supported version of TCP protocol.
BUILD_ID_STABLE = 199The build id of the last stable release.
ALLOW_LITERALS_ALL = 2Constant meaning both numbers and text is allowed in SQL statements.
LOCK_MODE_TABLE_GC = 2The lock mode that means table level locking is used for reads and
writes. If a table is locked, System.gc is called to close forgotten
connections.
BUILD_ID = 200The build id is incremented for each public release.
INITIAL_LOCK_TIMEOUT = 2000For testing, the lock timeout is smaller than for interactive use cases.
This value could be increased to about 5 or 10 seconds.
MEMORY_ARRAY = 24The memory needed by an array.
MEMORY_DATA = 24The memory needed by a object of class Data
MEMORY_OBJECT = 24The memory needed by a regular object with at least one field.
MEMORY_PAGE_DATA = 240The memory needed by an object of class PageData.
DEFAULT_MAX_LENGTH_INPLACE_LOB = 256The default maximum length of an LOB that is stored with the record
itself, and not in a separate place.
DEFAULT_LOCK_MODE = 3The default value for the LOCK_MODE setting.
LOCK_MODE_READ_COMMITTED = 3The lock mode that means read locks are acquired, but they are released
immediately after the statement is executed.
VERSION_MINOR = 4The minor version of this database.
MEMORY_ROW = 40The memory needed by a Row.
DEFAULT_PAGE_SIZE = 4096The default page size to use for new databases.
IO_BUFFER_SIZE = 4096The block size for I/O operations.
MIN_WRITE_DELAY = 5The minimum write delay that causes commits to be delayed.
SELECTIVITY_DEFAULT = 50The default selectivity (used if the selectivity is not calculated).
THROTTLE_DELAY = 50How often we check to see if we need to apply a throttling delay if SET
THROTTLE has been used.
DEFAULT_WRITE_DELAY = 500The default delay in milliseconds before the transaction log is written.
DEFAULT_MAX_MEMORY_UNDO = 50000The default value for the MAX_MEMORY_UNDO setting.
TRANSACTION_SNAPSHOT = 6SNAPSHOT isolation level of transaction.
MEMORY_FACTOR = 64This value is used to calculate the average memory usage.
VIEW_INDEX_CACHE_SIZE = 64The name of the index cache that is used for temporary view (subqueries
used as tables).
CACHE_SIZE_DEFAULT = 65536The default cache size in KB for each GB of RAM.
MEMORY_POINTER = 8The memory needed by a pointer.
SALT_LEN = 8The number of bytes in random salt that is used to hash passwords.
DEFAULT_HTTP_PORT = 8082The default port number of the HTTP server (for the H2 Console).
This value is also in the documentation and in the Server javadoc.
TCP_PROTOCOL_VERSION_9 = 9The TCP protocol version number 9.
TCP_PROTOCOL_VERSION_MIN_SUPPORTED = 9Minimum supported version of TCP protocol.
DEFAULT_TCP_PORT = 9092The default port of the TCP server.
This port is also used in the documentation and in the Server javadoc.
BUILD_VENDOR_AND_VERSIONIf H2 is compiled to be included in a product, this should be set to
a unique vendor id (to distinguish from official releases).
Additionally, a version number should be set to distinguish releases.
Example: ACME_SVN1651_BUILD3
FULL_VERSIONThe complete version number of this database, consisting of
the major version, the minor version, the build id, and the build date.
VERSIONThe version of this product, consisting of major version, minor
version, and build id.
BLOB_SEARCH = falseWhether searching in Blob values should be supported.
BUILD_SNAPSHOT = falseWhether this is a snapshot version.
|


| 396 | (A) | witħ a tenefułł toure þat to the town gaggede |
| 396 | (C) | with a dredefułł towre . þat ouur þe town hangedde |
| 397 | (D) | wiþ tenefułł touris þat ovir þe Cite goggid |
| 394 | (E) | with a wounder strong towr . þat ouer þe town lokyd |
| (Ex) | ---- no text ---- | |
| 410 | (L) | with a tenful toure þat ouer þe toun gawged |
| 380 | (P) | with a tenefułł turne þat ouer þe toune glayde |
| 390 | (U) | With a teneful toure / that ouer the toun gogges |
| (V) | ---- no text ---- |


--- layout: post title: 'Shorter fiction: Borin was here' date: 2010-12-04 21:23:36.000000000 +01:00 type: post parent_id: '0' published: true password: '' status: publish categories: - humble thoughts tags: - borin - humor - shorter fiction meta: _edit_last: '850381' _wp_old_slug: '' author: login: stmaarten email<EMAIL_ADDRESS>display_name: stmaarten first_name: '' last_name: '' ---
Borin quickly wrote this poem on a standing stone:
"Borin was here, he now is o'erthere
The brown predator that came a minute later could not read,
a slight, but deadly oversight in Borin's perfect plan.
In his final moments Borin could not stop this rhyme from popping up:
"Borin was here,
how appropriate the past tense now is, bear"


Simcty 3000 Linux Installer:
Works on Simcity 3000 and Unlimited(Needs to be The Linux Edition of them)
Simcity 3000 Unlimited Linux Installer Script made in python 2.7
GitHub Project Page here!
Download the Python Script here!
Warning: This script and the author of it is not responsible for any damages it might cause you including but not limited to: damaging your system, making your house burn, make you flunk at school or giving you stress. Use it at your own will and risk!
Requirements:
*In order to install Simciy 3000 (vanilla) or Unlimited you will need to have your legally purchased cdrom or legal backup iso of Simcity 3000/3000 unlimited Linux Edition. This program wont provide it or endorse piracy under any circumstances
*You are also required to have a machine running Python: 2.7
Please be aware Simcity 3000 and Simcity 3000 Unlimited for Linux are complete distinct versions of the game. If you bought the Windows version you can only run the game on a Windows machine or on a Linux machine through
Wine HQ. My Python script can only help the people who have the Loki Games Linux Edition of this game.
Instructions:
1:Download the Python Script here
2: Move your Simcity 3000 or Simcity 3000 Unlimited iso in the same directory of this python script installer and then launch the python installer
3: To launch the python script you will have to start the linux terminal and then type cd (directory where this python script is located) example: cd /home/YourUsername/Desktop/PythonScriptFolder
4: After that to launch it type in the terminal: python SCU3Installer.py
5: Enjoy the game!
Warning: in order to make the SCU3installer launcher(sc3u_2.0a-multilingual_x86.mojo.run) that you just downloaded run with this script you might need to go to its properities and mark in its permissions "Allow executing file as program"
FAQ
Your python script fails to download the setup installer!
It seens like sometimes the installer fails to finish downloading the installer. Due to the slow internet speeds of the website that hosts the old loki games setup installers. While we dont have a work around the best way to fix it is to download it manually here and then place it in the same folder of this script and your legal Simcity 3000 ISO backup. Which will make the installation work.
I´ve tried to install Simcity3000 on my linux machine using my Windows copy of Simcity 3000/3000 unlimited and your installer wont detect or accept them! Your software is broken!!!! Go fix it!!!!
As I stated above in the Readme of this python script github repository the installer will only be able to install and detect this game if its Simcity 3000 or Simcity 3000 Unlimited Linux Edition made by Loki Games. This Software isnt some kind of magic wizard that will be able to turn Simcity for windows into Simcity for linux. Please be aware that Sim City 3000 or Simcity 3000 Unlimited Linux Edition, made by Loki game is a complete distinct version of the Simcity 3000 or Simcity 3000 Unlimited made for Linux. If you want to use your windows version on a Linux machine please go use Wine HQ.
I have the Linux Edition. Why would I need your installer instead of the original one that comes in the CD that I bough back in the day?
You need my installer because Linux has changed a lot in the last 20 years and even if you are able to install it on your own you will probably run it with a lot of issues such as the game not running correctly, audio missing and other glitches in modern Linux machines. My Installer makes sure to install it perfectly in modern Linux Machines and it also install packages needed to make the audio of the game work in the newest Linux Distributions.
Will you ever port your python script to python 3?
Someday when I have enough free time to study and find the main differences between python 2 and python 3 and what would be the best way to convert each line in it. In the meantime I recommend you to install Python 2 to use my script.
Tested under: Linux Mint 17.3 Cinammon 64 bit and Deepin Linux 15.3 64 bit


Size Class
Definition
Line
44
of
System.Screen/Primitive.cm
Constructors & Destructor
public
nothrow
Size
()
public
nothrow
Size
(
int
w_,
int
h_)
Member Functions
public
static
nothrow
Size
Default
()
public
nothrow
bool
IsDefault
()
const
public
nothrow
String
<
char
>
ToString
()
const
Member Variables
public
int
h
public
int
w
Constructor& Destructor Details
Size Constructor
public
nothrow
Size()
Definition
Line
46
of
System.Screen/Primitive.cm
Size Constructor
public
nothrow
Size(
int
w_,
int
h_)
Definition
Line
49
of
System.Screen/Primitive.cm
Member Function Details
Default Static Member Function
public
static
nothrow
Size
Default()
Definition
Line
52
of
System.Screen/Primitive.cm
IsDefault Member Function
public
nothrow
bool
IsDefault()
Definition
Line
56
of
System.Screen/Primitive.cm
ToString Member Function
public
nothrow
String
<
char
> ToString()
Definition
Line
60
of
System.Screen/Primitive.cm


Plot of the Projections of the Globe
In the menus "Projection" and "Colour"‚ the settings in Fabric.ini
can be changed.
The distance between the great circles is written into the input
field on the right. The value should be a divisor of 90. The
'increment' is the distance between the the calculated points with
which the circles are plotted. It should be a divisor of the distance
between the circles. The tilt angle is the inclination of the N-S-axis.


{% extends 'ctflex/board/board.template.html' %} {% load cache %} {% block content %}
To look at other rounds’ scoreboards or the overall scoreboard, use the dropdown above.


This is a course project that aims at exploring design for panorama, 360 photo, and other immersive technologies. Due to the limitation of time, the scope is set as small as shooting panorama / 360 photo while traveling. Target users are people who would like to share their experience with family members and close friends.
In the past, people wrote journals and told stories when traveling. Today, we took photos and post them on Facebook, Instagram, Twitter, etc. The spirit of sharing have never been changed. When we are visiting some most spectacular spots, we really want to share the amazing scene in front of us with our family and friends. So we take a photo, or even better, a panorama. And what is next? Posting it on social channels sounds like a good choice, from which we get lots of likes. However, sometimes we need a little bit more than that. We really want to talk more about the scene, and start a conversation from there.
Panorama and 360 photo can present a bigger scene to audience, but it also brings the potential lost of focus. Therefore, Tags feature is designed for resolve this issue and help users add more personal comments in context.
Sharing the amazing scene with others is good, but there might be more we could do here. If user chooses to share it privately to another use or a group of users, a conversation UI will be integrated into the post so everybody involved can start a conversation using text or voice.


Provides an interface to read/write data from files as input/output streams.
More...
#include <btkBinaryFileStream_mmfstream.h>
|
| typedef std::ios_base::failure | failure |
| |
Provides an interface to read/write data from files as input/output streams.
This class is a low level class used by the class BinaryFileStream when possible (if the OS supports it). It is not advised to use this class directly even if the direct access to the buffer can speed the reading of a file (compared to the use of the class BinaryFileStream).
| btk::mmfstream::mmfstream |
( |
| ) |
|
|
inline |
Simple constructor which must use the method open() after.
| btk::mmfstream::mmfstream |
( |
const char * |
s, |
|
|
std::ios_base::openmode |
mode |
|
) |
| |
|
inline |
Constructor which opens the given filename s and options mode.
| bool btk::mmfstream::bad |
( |
| ) |
const |
|
inline |
| void btk::mmfstream::clear |
( |
std::ios_base::iostate |
state = std::ios_base::goodbit | ) |
|
|
inline |
Sets a new value for the error control state.
| void btk::mmfstream::close |
( |
| ) |
|
|
inline |
| bool btk::mmfstream::eof |
( |
| ) |
const |
|
inline |
| std::ios_base::iostate btk::mmfstream::exceptions |
( |
| ) |
const |
|
inline |
Returns the exception mask
| void btk::mmfstream::exceptions |
( |
std::ios_base::iostate |
except | ) |
|
|
inline |
| bool btk::mmfstream::fail |
( |
| ) |
const |
|
inline |
Checks if either failbit or badbit is set
| bool btk::mmfstream::good |
( |
| ) |
const |
|
inline |
Checks if the state of the stream is good for i/o operations
| bool btk::mmfstream::is_open |
( |
| ) |
const |
|
inline |
| void btk::mmfstream::open |
( |
const char * |
s, |
|
|
std::ios_base::openmode |
mode |
|
) |
| |
|
inline |
| const mmfilebuf * btk::mmfstream::rdbuf |
( |
| ) |
const |
|
inline |
Gets the associated file buffer object.
| std::ios_base::iostate btk::mmfstream::rdstate |
( |
| ) |
const |
|
inline |
Returns the current internal error state flags of the stream.
| mmfstream & btk::mmfstream::read |
( |
char * |
s, |
|
|
std::streamsize |
n |
|
) |
| |
| mmfstream & btk::mmfstream::seekg |
( |
std::streampos |
pos | ) |
|
|
inline |
Sets position of the get pointer
| mmfstream & btk::mmfstream::seekg |
( |
std::streamoff |
off, |
|
|
std::ios_base::seekdir |
dir |
|
) |
| |
|
inline |
Sets position of the get pointer
| mmfstream & btk::mmfstream::seekp |
( |
std::streampos |
pos | ) |
|
|
inline |
Sets position of put pointer
| mmfstream & btk::mmfstream::seekp |
( |
std::streamoff |
off, |
|
|
std::ios_base::seekdir |
dir |
|
) |
| |
|
inline |
Sets position of put pointer
| void btk::mmfstream::setstate |
( |
std::ios_base::iostate |
state | ) |
|
|
inline |
| std::streampos btk::mmfstream::tellg |
( |
| ) |
|
|
inline |
Gets position of the get pointer.
| mmfstream & btk::mmfstream::write |
( |
const char * |
s, |
|
|
std::streamsize |
n |
|
) |
| |


Library: Net
Package: HTTP
Header: Poco/Net/HTTPBasicCredentials.h
Description
This is a utility class for working with HTTP Basic Authentication in HTTPRequest objects.
Member Summary
Member Functions: authenticate, getPassword, getUsername, parseAuthInfo, proxyAuthenticate, setPassword, setUsername
Constructors
HTTPBasicCredentials
Creates an empty HTTPBasicCredentials object.
HTTPBasicCredentials
explicit HTTPBasicCredentials(
const HTTPRequest & request
);
Creates a HTTPBasicCredentials object with the authentication information from the given request.
Throws a NotAuthenticatedException if the request does not contain basic authentication information.
HTTPBasicCredentials
explicit HTTPBasicCredentials(
const std::string & authInfo
);
Creates a HTTPBasicCredentials object with the authentication information in the given string. The authentication information can be extracted from a HTTPRequest object by calling HTTPRequest::getCredentials().
HTTPBasicCredentials
HTTPBasicCredentials(
const std::string & username,
const std::string & password
);
Creates a HTTPBasicCredentials object with the given username and password.
Destructor
~HTTPBasicCredentials
Destroys the HTTPBasicCredentials.
Member Functions
authenticate
void authenticate(
HTTPRequest & request
) const;
Adds authentication information to the given HTTPRequest.
getPassword
const std::string & getPassword() const;
Returns the password.
getUsername
const std::string & getUsername() const;
Returns the username.
proxyAuthenticate
void proxyAuthenticate(
HTTPRequest & request
) const;
Adds proxy authentication information to the given HTTPRequest.
setPassword
void setPassword(
const std::string & password
);
Sets the password.
setUsername
void setUsername(
const std::string & username
);
Sets the username.
parseAuthInfo
void parseAuthInfo(
const std::string & authInfo
);
Extracts username and password from Basic authentication info by base64-decoding authInfo and splitting the resulting string at the ':' delimiter.
Variables
SCHEME
static const std::string SCHEME;


chromHMMviewR
is a package to visualize data from ChromHMM.
This package has been developped following this repository as a guide.
chromHMMviewR
To install chromHMMveiwR
, you have to run:
# install the devtools package from CRAN
install.packages("devtools")
# install chromHMMviewR from this Github repository
devtools::install_github("amitjavilaventura/chromHMMviewR")
If you use this package, please cite this repository and give it a star.
Go to the ChromHMM official website to get more information about how to use ChromHMM: http://compbio.mit.edu/ChromHMM/.


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. This takes the form of a template that describes the data structure. You use this template to encode your data structure into wire-streams that may be sent-to or read-from your peers. The underlying wire stream is platform independent, lossless, and may be used to interwork with a variety of languages and systems regardless of word size or endianness. Techniques exist to safely extend your data structure without breaking deployed programs that are compiled against the "old" format.
The idea behind Google's Protocol Buffers is that you define your
structured messages using a domain-specific language. This takes the
form of a .proto
source file. You pass this file through a
Google provided tool that generates source code for a target language,
creating an interpreter that can encode/decode your structured data. You
then compile and build this interpreter into your application program.
Depending on the platform, the underlying runtime support is provided by
a Google supplied library that is also bound into your program.
In SWI-Prolog, the wire stream interpreter is embodied in the form of a Definite Clause Grammar (DCG). It has a small underlying C-support library that loads when the Prolog module loads. This implementation does not depend on any code that is provided by Google and thus, is not bound by its license terms.
On the Prolog side, you define your message template as a list of
predefined Prolog terms that correspond to production rules in the DCG.
The process is not unlike specifiying the format of a regular
expression. To encode a message, X
, to wire-stream, Y
,
you pass a grounded template, X
, and a variable, Y
,
to protobuf_message/2. To
decode a wire-stream, Y
, to template, X
, you
pass an ungrounded template, X
, along with a grounded
wire-stream, Y
, to
protobuf_message/2. The
interpreter will unify the unbound variables in the template with values
decoded from the wire-stream.
The wire-stream consists of six primitive payload types, two of which have been deprecated. A primitive in the wire-stream is a multi-byte string that provides three pieces of information: a wire-type, a user-specified tag, and the raw payload. Except for the tag and its wire-type, protobuf payloads are not instantaneously recognizable because the wire-stream contains no payload type information. The interpreter uses the tag to associate the raw payload with a local host type specified by the template. Hence, the message can only be properly decoded using the template that was used to encode it. Note also that the primitive is interpreted according to the needs of a local host. Local word-size and endianness are dealt with at this level.
The following table shows the association between various "host types" used by several peer languages, and the primitives used in the wire-stream:
Prolog Wirestream C++ Java Notes double fixed64 double double integer64 fixed64 int64 long float fixed32 float float integer32 fixed32 int32 int integer varint int32/64 int/long 1, 2 unsigned varint uint32/64 int/long 2, 3 boolean varint bool boolean 2 enum varint int int 2 atom length delimited string String 4 codes length delimited string ByteString utf8_codes length delimited string ByteString 4 string length delimited string String 4
Notes:
A tag is a small integer that is present in every wire-stream primitive. The tag is the only means that the interpreter has to synchronize the wire-stream with its template. Tags are user defined for each term in each message of the wire-stream. It is important therefore, that they be chosen carefully and in such a way as to not introduce ambiguity.
A protobuf wire-stream is a byte string that is comprised of zero or more of the above multi-byte wire-stream primitives. Templates are lists of Prolog terms. Each term corresponds to a production rule in the DCG. The purpose of the template is to provide a recipe and value set for encoding and decoding a particular message. Each term in the template has an arity of two. The term's functor is the local "host type". Argument 1 is its tag, which must always be ground, and argument 2 is its associated value, which may or may not be ground.
Note: It is an error to attempt to encode a message using a template that is not ground. Decoding a message into a template that has unbound variables has the effect of unifying the variables with their corresponding values in the wire-stream.
Map a Prolog structure to a Protocol Buffer:
command(add(X,Y), Proto) :- Proto = protobuf([atom(1, command), atom(2, add), integer(3, X), integer(4, Y) ]).
Later on:
... prepare X, Y for command ... command(add(X,Y), Proto), protobuf_message(Proto, Msg), ... send the message ...
Proto is the protobuf template. Each template describes exactly one
message. Msg is the wire-stream. If you are interworking with other
systems and languages, then the protobuf templates that you supply to
protobuf_message/2 must
be equivalent to those described in the
.proto
file that is used on the other side.
The protobuf grammar provides a reserved word, optional
,
that indicates that the production rule that it refers to may appear
once or not at all in a protobuf message. Since Prolog has its own means
of alternation, this reserved word is not supported on the Prolog side.
It is anticipated that customary Prolog mechanisms for nondeterminism
(e.g. backtracking) will be used to generate and test alternatives.
It is possible to specify homogeneous vectors of things (e.g. lists
of numbers) using the repeated
attribute. You specify a
repeated field as follows:
repeated(22, float([1,2,3,4])), repeated(23, enum(tank_state([empty, half_full, full]))).
The first clause above, will cause all four items in the list to be encoded in the wire-stream as IEEE-754 32-bit floating point numbers, all with tag 22. The decoder will aggregate all items in the wire-stream with tag 22 into a list as above. Likewise, the all items listed in the second clause will be encoded in the wire-stream according to the mapping defined in an enumeration (described below) tank_state/2, each with tag 23.
Notes:
Beware that there is no explicit means to encode an empty set. The
protobuf specification provides that a repeated
field may
match a tag zero or more times. The empty set, while legal, produces no
output on encode. While decoding a repeated
term, failure
to match the specified tag will yield an empty set of the specified host
type.
The protobuf grammar provides a variant of the repeated
field known as "packed." Packed, repeated fields are currently not
supported by our interpreter.
It is possible to embed one protocol buffer specification inside
another using the embedded
term. The following example
shows a vector of numbers being placed in an envelope that contains a
command enumeration.
Enumerations are a compact method of sending tokens from one system
to another. Most occupy only two bytes in the wire-stream. An
enumeration requires that you specify a callable predicate like commands/2,
below. The first argument is an atom specifying the name of token, and
the second is an non-negative integer that specifies the token's value.
These must of course, match a corresponding enumeration in the
.proto
file.
Note: You must expose this predicate to the protobufs module by assigning it explicitly.
protobufs:commands(Key, Value) :- commands(Key, Value). commands(square, 1). commands(decimate, 2). commands(transform, 3). commands(inverse_transform, 4). basic_vector(Type, Proto) :- vector_type(Type, Tag), Proto = protobuf([ repeated(Tag, Type) ]). send_command(Command, Vector, Msg) :- basic_vector(Vector, Proto1), Proto = protobuf([enum(1, commands(Command)), embedded(2, Proto1)]), protobuf_message(Proto, Msg).
Use it as follows:
?- send_command(square, double([1,22,3,4]), Msg). Msg = [8, 1, 18, 36, 17, 0, 0, 0, 0, 0, 0, 240, 63, 17, 0, 0, 0, 0, 0, 0, 54, 64, 17, 0, 0, 0, 0, 0, 0, 8, 64, 17, 0, 0, 0, 0, 0, 0, 16, 64]. ?- send_command(Cmd, V, $Msg). Cmd = square, V = double([1.0, 22.0, 3.0, 4.0]) .
Compatibility Note: The protobuf grammar (protobuf-2.1.0) permits enumerations to assume negative values. This requires them to be encoded as integers. But Google's own Golden Message unit-test framework has enumerations encoded as unsigned. Consequently, parsers that encode them as integers cannot properly parse the Golden Message. So it's probably a good idea to avoid negative values in enumerations. Our parser forbids it anyway.
Using Protocol Buffers, it is quite an easy matter to specify fixed data structures and homogeneous vectors like one might find in languages like C++ and Java. It is however, quite another matter to interwork with these languages when requirements call for working with compound structures, arrays of compound structures, or unstructured collections (e.g. bags) of data.
At bottom, a wire-stream is nothing more than a concatenated stream of primitive wire type strings. As long as you can associate a tag with its host type in advance, you will have no difficulty in decoding the message. You do this by supplying the structure. Tell the parser what is possible and let the parser figure it out on its own, one production at a time. An example may be found in the appendix.
Protocol Buffer Groups provide a means for constructing unitary messages consisting of ad-hoc lists of terms. The following protobuf fragment shows the definition of a group carrying a complex number.
Proto = group(2, [ double(1, Real_part), double(2, Img_part) ]).
Groups have been replaced by embedded messages, which are slightly less expensive to encode.
Performance can be significantly improved using a strategy of precompiling the constant portions of your message. Enumerations for example, are excellent candidates for precompilation. Using protobuf_message/3, the precompiled portion of the message is inserted directly in the wire-stream on encode, and is unified with, and removed from the wire-stream on decode. The following shows how the "send_command" example above, can be converted to precompiled form:
:- dynamic precompiled_message/3. send_precompiled_command(Command, Vector, Msg) :- basic_vector(Vector, Proto1), precompiled_message(commands(Command), Msg, Tail), protobuf_message(protobuf([embedded(3, Proto1)]), Tail). precompile_commands :- abolish(precompiled_message/3), forall(protobufs:commands(Key, _), ( Proto = protobuf([atom(1, command), enum(2, commands(Key))]), protobuf_message(Proto, Msg, Tail), assert(precompiled_message(commands(Key), Msg, Tail)) )), compile_predicates([precompiled_message/3]). * * * :- initialization precompile_commands.
You can extend the parser to support your own compound host types.
These are treated as first class entities by the parser. That is they
can be used either by themselves, or in repeated
and embedded
clauses just as any other host type would be. You do this by hooking
into the parser and adding your own message_sequence
productions. Your hook eventually calls back into the parser with your
substitution/expansion protobuf, which is then embedded in the wire
stream. Recursive structures can be defined this way. A simple example
of a recursive XML like structure is shown in the appendix.
In this example we demonstrate managing a recursive structure like
XML. The structure shown in xml_proto/1
below, is similar to the structure returned by load_xml_file/2,
which is part of the SGML library. We supply three message_sequence
decorators: kv_pair
, xml_element
, and aux_xml_element
.
These are treated as first class host types.
:- multifile protobufs:message_sequence/5. protobufs:message_sequence(Type, Tag, Value) --> { my_message_sequence(Type, Value, Proto) }, protobufs:message_sequence(embedded, Tag, Proto), !. % % On encode, the value type determines the tag. And on decode % the tag to determines the value type. % guard(Type, Value) :- ( nonvar(Value) -> is_of_type(Type, Value); true). my_message_sequence(kv_pair, Key=Value, Proto) :- Proto = protobuf([ atom(30, Key), X]), ( ( guard(integer, Value), X = integer(31, Value)); ( guard(float, Value), X = double(32, Value)); ( guard(atom, Value), X = atom(33, Value))). my_message_sequence(xml_element, element(Name, Attributes, Contents), Proto) :- Proto = protobuf([ atom(21, Name), repeated(22, kv_pair(Attributes)), repeated(23, aux_xml_element(Contents))]). my_message_sequence(aux_xml_element, Contents, Proto) :- functor(Contents, element, 3), Proto = protobuf([xml_element(40, Contents)]). my_message_sequence(aux_xml_element, Contents, Proto) :- Proto = protobuf([atom(43, Contents)]). xml_proto([element(space1, [foo='1', bar='2'], [fum, bar, element(space2, [fum=3.1415, bum= -14], ['more stuff for you']), element(space2b, [], [this, is, embedded, also]), to, you])]). test_xml(X, Y) :- Proto = protobuf([repeated(20, xml_element(X))]), protobuf_message(Proto, Y). % And test it: ?- xml_proto(X), test_xml(X,Y), test_xml(Z,Y), Z == X. X = [element(space1, [foo='1', bar='2'], [fum, bar, element(space2, [fum=3.1415, bum= -14], ['more stuff for you'] ), element(space2b, [], [this, is|...] ), to, you])], Y = [162, 1, 193, 1, 170, 1, 6, 115, 112|...], Z = [element(space1, [foo='1', bar='2'], [fum, bar, element(space2, [fum=3.1415, bum= -14], ['more stuff for you'] ), element(space2b, [], [this, is|...] ), to, you])]
A protobuf description that is compatible with the above wire stream follows:
message kv_pair { required string key = 30; optional sint64 int_value = 31; optional double float_value = 32; optional string atom_value = 33; } message aux_xml_element { optional string atom = 43; optional xml_element element = 40; } message xml_element { required string name = 21; repeated kv_pair attributes = 22; repeated aux_xml_element contents = 23; } message XMLFile { repeated xml_element elements = 20; }
Verify the wire stream using the protobuf compiler's decoder:
$ protoc --decode=XMLFile pb-vector.proto <tmp98.tmp elements { name: "space1" attributes { key: "foo" atom_value: "1" } attributes { key: "bar" atom_value: "2" } contents { atom: "fum" } contents { atom: "bar" } contents { element { name: "space2" attributes { key: "fum" float_value: 3.1415 } attributes { key: "bum" int_value: -14 } contents { atom: "more stuff for you" } } } contents { element { name: "space2b" contents { atom: "this" } contents { atom: "is" } contents { atom: "embedded" } contents { atom: "also" } } } contents { atom: "to" } contents { atom: "you" } }
In the Prolog client:
vector_type(double(_List), 2). vector_type(float(_List), 3). vector_type(integer(_List), 4). vector_type(integer64(_List), 5). vector_type(integer32(_List), 6). vector_type(unsigned(_List), 7). vector_type(codes(_List), 8). vector_type(atom(_List), 9). vector_type(string(_List), 10). vector(Type, B):- vector_type(Type, Tag), Proto = protobuf([ repeated(Tag, Type) ]), protobuf_message(Proto, B).
A protobuf description that is compatible with the above wire stream follows:
message Vector { repeated double double_values = 2; repeated float float_values = 3; repeated sint32 integer_values = 4; repeated fixed64 integer64_values = 5; repeated fixed32 integer32_values = 6; repeated uint32 unsigned_values = 7; repeated bytes bytes_values = 8; repeated string atom_values = 9; repeated string string_values = 10; }
A typical application might consist of an abstract adapter class along with a collection of concrete subclasses that refine an abstract behavior in order to hide the interaction with the underlying protobuf interpreter. An example of such a class written in C++ may be found in the demos.
On the Prolog side:
:- meta_predicate ~>(0,0). :- op(950, xfy, ~>). ~>(P, Q) :- setup_call_cleanup(P, (true; fail), assertion(Q)). write_as_proto(Vector) :- vector(Vector, Wirestream), open('tmp99.tmp', write, S, [type(binary)]) ~> close(S), format(S, '~s', [Wirestream]), !. testv1(V) :- read_file_to_codes('tmp99.tmp', Codes, [type(binary)]), vector(V, Codes).
Run the Prolog side:
?- X is pi, write_as_proto(double([-2.2212, -7.6675, X, 0, 1.77e-9, 2.54e222])). X = 3.14159. ?- testv1(Vector). Vector = double([-2.2212, -7.6675, 3.14159, 0.0, 1.77e-09, 2.54e+222]) ?-
Verify using the protobuf compiler:
$ protoc --decode=Vector pb-vector.proto <tmp99.tmp double_values: -2.2212 double_values: -7.6675 double_values: 3.1415926535897931 double_values: 0 double_values: 1.77e-09 double_values: 2.5400000000000002e+222
The following example shows how one can specify a Protocol Buffer message that can deal with variable-length, unstructured bags of numbers:
compound_protobuf(complex(Real, Img), group(12, [double(1, Real), double(2, Img)])). compound_protobuf(float(Val), float(13, Val)). compound_protobuf(double(Val), double(14, Val)). compound_protobuf((Num rdiv Den), group(15, [integer(1, Num), integer(2, Den)])). compound_protobuf(integer(Val), integer(16, Val)). protobuf_bag([], []). protobuf_bag([ Type | More], Msg) :- compound_protobuf(Type, X), Proto = protobuf([embedded(1, protobuf([X]))]), protobuf_message(Proto, Msg, Msg1), protobuf_bag(More, Msg1), !.
Use it as follows:
?- protobuf_bag([complex(2,3), complex(4,5), complex(6,7), 355 rdiv -113, integer(11)], X). X = [10, 20, 99, 9, 0, 0, 0, 0, 0|...]. ?- protobuf_bag(Y, $X). Y = [complex(2.0, 3.0), complex(4.0, 5.0), complex(6.0, 7.0), 355 rdiv -113, integer(11)].
A protobuf description that is compatible with the above wire stream follows:
message compound_protobuf { optional group Complex = 12 { required double real = 1; required double img = 2; }; optional group Fraction = 15 { required sint64 num = 1; required sint64 den = 2; }; optional float float = 13; optional double double = 14; optional sint32 integer = 16; } message protobuf_bag { repeated compound_protobuf bag = 1;
Verify using the protobuf compiler's decoder:
$ protoc --decode=protobuf_bag pb-vector.proto <tmp96.tmp bag { Complex { real: 2 img: 3 } } bag { Complex { real: 4 img: 5 } } bag { Complex { real: 6 img: 7 } } bag { Fraction { num: 355 den: -113 } } bag { integer: 11 }
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. This takes the form of a template that describes the data structure. You use this template to encode and decode your data structure into wire-streams that may be sent-to or read-from your peers. The underlying wire stream is platform independent, lossless, and may be used to interwork with a variety of languages and systems regardless of word size or endianness. Techniques exist to safely extend your data structure without breaking deployed programs that are compiled against the "old" format.
The idea behind Google's Protocol Buffers is that you define your
structured messages using a domain-specific language and tool set. In
SWI-Prolog, you define your message template as a list of predefined
Prolog terms that correspond to production rules in the Definite Clause
Grammar (DCG) that realizes the interpreter. Each production rule has an
equivalent rule in the protobuf grammar. The process is not unlike
specifiying the format of a regular expression. To encode a template to
a wire-stream, you pass a grounded template, X
, and
variable, Y
, to
protobuf_message/2. To
decode a wire-stream, Y
, you pass an ungrounded template, X
,
along with a grounded wire-stream, Y
, to
protobuf_message/2. The
interpreter will unify the unbound variables in the template with values
decoded from the wire-stream.
For an overview and tutorial with examples, see protobufs_overview.txt
.
Examples of usage may also be found by inspecting test_protobufs.pl
.
| Template | is a protobuf grammar specification. On decode, unbound variables in the Template are unified with their respective values in the Wire_stream. On encode, Template must be ground. |
| Wire_stream | is a code list that was generated by a protobuf encoder using an equivalent template. |


Animal protesters effective?
by Miriam HalpennyMonday morning, a group of environmental and animal rights activists chained themselves to the doors of Interior Savings in Kelowna in an effort to get the credit union to stop sponsoring Ribfest.
The group's demands were not met, and members were removed by RCMP after several hours.
Castanet hit the streets to find out if people think this way of protesting is effective.
Send your thoughts to letters@castanet.net.


Answer TRUE or FALSE.
A company wants to use a system where they randomly assign each customer a 9-digit ID (so there are 1 billion possible ID numbers). Of course, there is a chance that two customers will be assigned the same ID. But the company figures that risk is OK if the odds are only one in a million. They expect to assign IDs to 1000 customers. But the chance of collision is much higher than one in a million.
While it is true that the last customer given an ID has about one chance in a million of sharing it with another customer (actually, the chance is 999/1,000,000,000 if 999 IDs are already assigned)...
... this logic does not account for the fact that any of the previous 998 assignments might also have caused a collision.
So the chance for a collision is rather higher than one in a million.


indep-pairwise params:
Independent loci retained:
System Message: ERROR/3 (None, line 26)
Content block expected for the "container" directive; none found.
.. container:: :name: attachments


jorisvanzundert / simsome
Simsome: example animation
Example of an animation of a simulated agent in an epistemic world. More information on the Simsome project you'll find on GitHub: https://github.com/jorisvanzundert/simsome


swserver, v1.4.0 October 14th, 2016
SignWriting is the international script for writing the sign languages of the world. The SignWriting Server provides online resources for SignWriting applications and users. The server accepts HTTP requests and responds with SVG or JSON data. The SignWriting Server is built with the PHP SLIM Framework v2.6.
The primary site is available on the Center for Sutton Movement Writing server.
A mirror site is available on Wikimedia Labs.
The SignWriting server creates SVG images for individual symbols using symbol keys and completed 2-dimensional signs using Formal SignWriting. Styling strings are supported, offering coloring and sizing customizations.
Query strings are a concise representation of a much larger and detailed set of regular expressions. Each query string is transformed into one or more regular expressions that can be used to search a text of Formal SignWriting. Additionally, Formal SignWriting strings can be converted into several types of query strings, each of which can be transformed into regular expressions.
The countries of the world are described with SVG shapes and flag images. Listings of languages and puddle collections are available for each country.
All of the SignPuddle Online data is available as SQLite 3 databases. These databases can be downloaded individually. The various puddle collections can be listed, limited by sign language or individual code. For each sign language, a default public dictionary has been selected so that ISO 639-3 codes can be used rather than a puddle code. With a puddle query, individual entries can be access with sign language directly. With a puddle search, individual entries can be access with spoken language. Additional search options are available for listings of individual signs and terms. Additionally, entries can be retrieved by the dates created or updated.
Copy the SignWriting Server files to the root web server directory or to a sub-directory.
Any server that supports PHP and SQLite 3 will be able to run the SignWriting Server.
The main database is available from the SignWriting Server Data project with only the symbol information.
The SignPuddle Online databases are available on SignBank.
The main database is available as swserver.db.
The individual databases are available in the puddle subdirectory.
A shell script is available to download the main database.
A shell script is available to mirror all of the available puddles on SignBank with a single command.
If a web server is not already running, the start server shell script can be used to start the built-in PHP web server.
The SignWriting Server project documents are created with command-line tools.
The SignWriting Server API is documented using API Blueprint. This specification offers powerful tooling such as automatic HTML document generation and mock servers. https://apiblueprint.org/
The API Blueprint for the Guide is embedded in the main index.php file. The API Blueprint for the Example document is created using ‘curl’ with ‘curl-trace-parser’.
The SignWriting Server includes example API calls encoded as JSON data. These examples are used to create the API Blueprint for the Example document and the JavaScript function calls for the Run HTML page.
Shell scripts with more, grep, cat, and cut
jq - like “‘sed”’ for JSON data
curl - communicate with a server from the command line
curl-trace-parser - reformat curl output
hiro - create HTML documents from API Blueprints
iglo - create large HTML documents when hiro fails
./buils.sh - Creates the Index and Guide documents. Creates shell script and JavaScript function calls from JSON example data.
./run.sh - Executes the Example shell script and collates the results into the Example document.
./release.sh - Calls the build.sh script and then the run.sh script.
./example.sh - Creates the example html document when hiro fails for large files.
/ - root directory with HTML documentation and PHP server
/Slim - directory for the Slim Framework v2.6 code
/include - directory for other PHP files and function libraries
/data - directory for the SignWriting Server databases
/tools - directory for automation and document creation
/tools/input - directory of tool inputs, such as template.html
/tools/output - directory of processed output
/tools/log - directory of example request/response API calls
README.md - read me file in markdown
index.php - main file for handling requests, with embedded API Blueprint
Example.json - example api calls in JSON data format
Run.html - html page uses example api calls to access a server
index.html - Created from README.md
tools/output/Guide.md - Created from index.php
Guide.html - Created from tools/output/Guide.md
tools/output/Example.sh - Created from Example.json
tools/output/Example.md - Created from output of tools/output/Example.sh
Example.html - Created from tools/output/Example.md
Run.js - Created from Example.json and used in Run.html
Stephen E Slevinski Jr
<EMAIL_ADDRESS>http://slevinski.github.io
http://www.slideshare.net/StephenSlevinski/presentations
The Formal SignWriting character encoding used in the SignWriting Server is defined in an Internet Draft submitted to the IETF: draft-slevinski-formal-signwriting. The document is improved and resubmitted every 6 months. The character design has been stable since January 12, 2012. The current version of the Internet Draft is 00. The next version is planned for April 2017.
This is a work in progress. Feedback, bug reports, and patches are welcomed.
MIT
expand API for users
expand API for create, update, and delete
1.4.0 - Oct 14th, 2016: improved styling string and new Sutton SignWriting fonts
1.3.0 - May 2nd, 2016: new world group, added listings for puddle signs and terms
1.2.0 - Dec 17th, 2015: list puddles, download databases, custom limits, sorting, and date retrieval
1.1.0 - Nov 25th, 2015: added query and search for puddle data
1.0.0 - Nov 5th, 2015: initial public release


Copyright © Yariv Sadan 2006-2007
Authors: Yariv Sadan.
Introduction
Directory Structure
Components
Models
Controllers
Views
Containers
The App Controller
Yaws Configuration
ErlyWeb is a component-oriented web development framework that simplifies the creation of web applications in Erlang according to the tried-and-true MVC pattern. ErlyWeb's goal is to let web developers enjoy all the benefits of Erlang/OTP while creating web applications with simplicity, productivity and fun.
ErlyWeb is designed to work with Yaws, a high-performance Erlang web server. For more information on Yaws, visit http://yaws.hyber.org.
To install ErlyWeb, obtain the latest zip file from http://erlyweb.org and unzip it in your root Erlang code path. This path varies depending on your operating system (on OS X, it's '/usr/local/lib/erlang/lib'). If you don't know your path, you can discover it by starting the Erlang shell and calling "code:lib_dir()." (note that the last directory of the code path always erlang/lib).
ErlyWeb applications have the following directory structure:
[AppName]/ src/ contains non-component source files [AppName]_app_controller.erl the app controller [AppName]_app_view.rt the app view components/ contains controller, view and model source files www/ contains static assets ebin/ contains compiled .beam files
where AppName is the name of the application. The 'src', 'components' and 'www' directories may contain additional subdirectories, whose contents are of the same type as those in the parent directory.
An ErlyWeb component is made of a controller and a view, both of which are Erlang modules. Controllers may use one or more models, but this isn't required.
(Technically, a component can be implemented without a view, but most components have views.)
Controllers are implemented in Erlang source files. Views are typically implemented in ErlTL files, but views can be implemented in plain Erlang as well. The controller file is named '[ComponentName]_controller.erl' and the view file is named '[ComponentName]_view.[Extension]', where [ComponentName] is the name of the component, and [Extension] is 'erl' for Erlang files and 'et' for ErlTL files.
When ErlyWeb receives a request such as http://hostname.com/foo/bar/1/2/3
,
ErlyWeb interprets it as follows: 'foo' is the component name, 'bar' is the
function name, and ["1", "2", "3"]
are the parameters (note that
parameters from browser requests are always strings).
When only the component's name is present, ErlyWeb assumes the request is
for the component's 'index' function and with no parameters (i.e.
http://hostname.com/foo
is equivalent to http://hostname.com/foo/index
).
If the module 'foo_controller' exists and it exports the function
'bar/4', ErlyWeb invokes the function foo_controller:bar/4
with the parameters [A, "1", "2", "3"]
, where A is the Arg record
that Yaws passes into the appmod's out/1 function. (For more information,
visit http://yaws.hyber.org/.)
ErlyWeb treats all Erlang modules whose names don't end with '_controller' or '_view' and whose files exist under 'src/components' as models. If such modules exist, erlyweb:compile() passes their names to erlydb:code_gen() in order to generate their ErlyDB database abstraction functions.
If your application uses ErlyDB for database abstraction, you have to call erlydb:start() before erlyweb:compile() (otherwise, the call to erlydb_codegen() will fail). If you aren't using ErlyDB, don't keep any models in 'src/components' and then you won't have to call erlydb:start().
Controllers contain most of your application's logic. They are the glue between Yaws and your applications models and views.
Controller functions always accept the Yaws Arg for the request as the
first parameter, and they may return any of the values that Yaws
appmods may return (please read
the section below on the {response, Elems}
tuple to avoid
running into trouble). In addition, controller functions may return
a few special values, which are listed below with their meanings
(note: 'ewr' stands for 'ErlyWeb redirect' and 'ewc' stands for 'ErlyWeb
Component.').
ewr
Redirect the browser to the application's root url.
{ewr, ComponentName}
Redirect the browser to the component's default ('index')
function
{ewr, ComponentName, FuncName}
Redirect the browser to the URL for the given component/function combination.
{ewr, ComponentName, FuncName, Params}
Redirect the browser to the URL with
the given component/function/parameters combination.
{data, Data}
Call the view function, passing into it the Data variable as a parameter.
{ewc, A}
Analyze the Yaws Arg record 'A'. If the request matches a component,
render the component and send the result to the browser.
Otherwise, return {page, Path}
, where Path is the Arg's appmoddata field.
{ewc, ComponentName, Params}
Render the component's 'index' function with the given parameters
and send the result to the view function.
{ewc, ComponentName, FuncName, Params}
Render the component's function with the given parameters, and send
the result to the view function.
{ewc, ControllerModule, ViewModule, FuncName, Params}
This tuple lets you specify exacly which controller and
view modules ErlyWeb uses to render the sub-component. It is considered for
advanced uses only.
{replace, Ewc}
This tuple, which was introduced in ErlyWeb 0.6, tells ErlyWeb to
render a different component from the requested one (the new component, Ewc
,
can be described using any of the 'ewc' tuples listed above).
This mechanism is conceptually similar to an internal redirect.
It is useful, for example, when you want multiple components to share
a common error screen. Instead of having multiple view functions
check if the controller result indicates an error has occurred, you can
use the replace
tuple to simply redirect the rendering to an error
component.
Controller functions may also return (nested) lists of 'ewc' and 'data' tuples, telling ErlyWeb to render the items in their order of appearance and then send the list of their results to the view function. This feature lets you build components that are composed of a mix of dynamic data and one or more sub-components.
If a component is only supposed to be used as a subcomponent, you should
implement the function "private() -> true.
" in its controller.
This tells ErlyWeb to call exit({illegal_request, Controller})
when clients try to access the component by requesting
its corresponding URL directly.
ErlyWeb provides the infrastructure for rendering components and redirecting
to other components in the same application. This is sufficient for simple
applications, but sometimes you may want to return
to Yaws tuples that Yaws understands and that aren't directly
supported by ErlyWeb (these are documented
at http://yaws.hyber.org/yman.yaws?page=yaws_api). A common requirement,
for example, is to instruct Yaws to include arbitrary HTTP headers, such as
cookies, in the response Yaws sends to the browser.
ErlyWeb lets you do this by returning a tuple of the
form {response, Elems}
from controller functions.
The second element in the {response, Elems}
is a list of values that
ErlyWeb should return to Yaws verbatim, with the exception of the (optional)
{body, Body}
for HTML or {body, MimeType, Body}
tuple and any of the ewr
tuples listed above (ErlyWeb translates the latter into their redirect_local
equivalents). If, in addition to returning standard Yaws tuples, you want
ErlyWeb to render the response's body using the component's view, you can
include the {body, Body}
or {body, MimeType, Body}
tuple in Elems
.
Body
may be any single ewc
or data
tuple, or a list thereof.
ErlyWeb renders the elements of Body
, sends the result to the view function,
and embeds the resulting iolist in an {html, Iolist}
tuple prior to
returning it to Yaws.
There is currently a restriction on the usage of {response, Elems}
: only the
top-level component for the request may return the
{response, Elems}
tuple. Sub-components may return only data
and/or
ewc
tuples. This restriction makes sense because you normally only use
sub-components for rendering segments of the response's body and not
for setting HTTP headers or implementing arbitrary application logic.
ErlyWeb lets you implement the before_call/2 and before_return/3 hooks in controllers to intercept function calls before they are applied and/or manipulate controller return values before ErlyWeb processes them.
The signature of before_call/2 is
before_call(FuncName::atom(), Params::[term()]) -> {NewFuncName::atom(), NewParams::[term()]}
You can use the before_call/2 hook to change the controller function ErlyWeb calls and/pr the parameters ErlyWeb passes to the function. This hook can be convenient, for example, for implementing authentication logic for some or all functions of a controller.
The signature of before_return/3 is
before_return(FuncName::atom(), Params::[term()], Response::term()) -> NewResponse::term()
By implementing the before_return/3 hook, you can change all return values based on the names and/or parameters of their originating controller functions. This hook can simplify the definition of response elements such HTTP headers common to some or all of a controller's functions.
ErlyWeb lets you implement the after_render/3 hook in controllers to get access to the rendered output. Teh
The signature of after_render/2 is
after_render(FuncName::atom(), Params::[term()], Rendered::iolist()) -> Ignored::any().
You can use the after_render/3 hook to implement a granular caching system.
Views are Erlang modules whose functions return iolists (nested lists of strings and/or binaries). A view function that ErlyWeb uses has the same name as its corresponding controller function, and it accepts a single parameter, which is the result of ErlyWeb's processing of the controller function's return value.
Containers are ErlyWeb components in which other components can be nested. ErlyWeb contains no special logic to enable containers; 'container' is just a word used to describe components that applications use in a special way.
What sets containers apart from standard components is that containers'
controller functions accept as parameters
ewc
and/or data
tuples representing nested sub-components.
The controller functions include those parameters in their return values,
telling ErlyWeb to render the nested components and pass the results
to the container's corresponding view functions. The view functions embed
the rendered subcomponents in the container's static HTML,
and ErlyWeb returns the final result Yaws.
The code below illustrates how to implement a
simple HTML container. The container's controller function tells ErlyWeb
to renders its sub-component (index/2's Ewc
parameter), and pass the result
to the component's view, which defines a basic HTML page.
-module(html_container_controller). -export([index/2, private/0]). %% tells ErlyWeb to reject direct HTTP requests for this %% container private() -> true. index(_A, Ewc) -> Ewc.html_container_view.et:
<%@ index(Data) %>   <title>My ErlyWeb App</title>   <% Data %>
The example below shows how to pass multiple 'song' components into an 'album' container, and show the result in the 'home' component.
song_controller.erl:index(A, Num, Title) -> {data, {integer_to_list(Num), Title}}.song_view.et:
<%@ index({Num, Title}) %> <% Num %>: <% Title %>
album_controller.erl:
index(A, Title, Songs) -> [{data, Title}, Songs].album_view.et:
<% index([Title, Songs]) %> album title: <% Title %>
 songs:
 <% Songs %> home_controller.erl: ``` index(A) -> Songs = [{ewc, song, [A, 1, <<"Back in the U.S.S.R">>]}, {ewc, song, [A, 2, <<"Dear Prudence">>]}], {ewc, album, [A, <<"White Album">>, Songs]}.home_view.et:
<% index(Album) %> Your favorite album is:<br/> <% Album %> == The App Controller == ErlyWeb applications have a module called [AppName]_app_controller, whose source file is in the 'src' directory by convention. The app controller provides the entry-point into ErlyWeb applications via the hook/1 function. Starting from ErlyWeb 0.6, the app controller can also have an error-trapping, error/3. === hook/1 === The signature for hook/1 is ``` hook(A::arg()) -> hook_result() | [hook_result()] hook_result = ewc() | yaws_term() | response() | {phased, Ewc::ewc() | Response::response(), fun(ExpandedEwc::ewc(), Data::iolist()) -> FinalEwc::ewc()} ewc() = any `ewc' tuple yaws_term() = any legal Yaws appmod return value response() = a tuple of the form {response, [Elems::response_elem()]} response_elem() = yaws_term() | {body, ewc()}
(Note: support for the response() return value was introduced in ErlyWeb 6.2.)
The simplest way of telling ErlyWeb to process a client request is to implement hook/1 as follows:
hook(A) -> {ewc, A}.
This tells ErlyWeb to check if the component that's mapped to the
request's URL is a top-level component (i.e., it doesn't implement
private() -> true.
). If it is top-level, ErlyWeb renders the component
and returns the to Yaws. Otherwise, ErlyWeb calls
exit({illegal_request, ControllerName}).
Warning: ErlyWeb only checks if tuples of the form {ewc, A}
represent
top-level components. If you return a different ewc
tuple (e.g. one
returned by calling erlyweb:get_initial_ewc/1
), ErlyWeb expects you
to ensure the safety of your components manually.
In ErlyWeb 0.5, the phased
return type was introduced to faciliate
the conditional embedding of any rendered data in containers
(before ErlyWeb 0.5, a similar, but weaker functionality was provided by
app views, which ErlyWeb no longer supports). By returning
{phased, Ewc, Fun}
, you are instructing ErlyWeb to first render the
requested component, and if the result includes a rendered
iolist (i.e., the requested component didn't return only headers),
then nest the resulting iolist in a container before returning it.
This approach is superior to directly embedding the requested component in a
container because it allows the requested component to return headers
(sub-components aren't allowed to return the {response, Elems}
tuple,
as discussed above). In addition, this approach lets ErlyWeb skip the
unnecessary rendering of the container when the requested component
returns only headers.
Consider this trivial example: returning
{phased, {ewc, A}, fun(_Ewc, Data) -> {data, Data} end}
is tantamount to returning
{ewc, A}
Another example: the return value below
{phased, {ewc, A}, fun(_Ewc, Data) -> {html_container, index, [A, {data, Data}]} end}
tells ErlyWeb to embed any rendered data in html_container by passing
the parameters [A, {data, Data}]
to its 'index' function.
Starting from ErlyWeb 0.6, the app controller may implement an error-trapping function whose signature is
error(A, Ewc, Err) -> result()
When ErlyWeb catches an exit signal when rendering a component, ErlyWeb tries to call the app controller's error/3 function. error/3's parameters are the Yaws arg, the Ewc tuple representing the original request, and the second element of the {'EXIT', Err} tuple that ErlyWeb has caught. error/3 may return any of the values that hook/1 may return, allowing you to use ErlyWeb components to render an error page.
App controllers may implement two additional functions that ErlyWeb uses: before_compile/1 and after_compile/1. These functions let you hook into the compilation process and extend it in arbitrary ways. Both functions take a single parameter indicating the last compilation time (as returned from calendar:local_time()), or 'undefined' if the last compilation time is unknown.
docroot = /path/to/app/www appmods = <[UrlPrefix], erlyweb> <opaque> appname = [AppName] </opaque>
where AppName is the name of your application and UrlPrefix is the URL prefix that Yaws uses to identify requests for this application (common values are '/[AppName]', for deploying multiple applications on the same server, or '/', for deploying a single application).
Note: It is recommended to use ErlyWeb with Yaws v1.66 and above.