Data structure server.
Knuckleball is an in-memory data structure server. It provides a language with a syntax similar to that of Smalltalk to create and manipulate simple data types like booleans, characters, integers, floats and strings, and containers like vectors, sets and dictionaries. Knuckleball is implemented as a single-threaded and asynchronous server, so it can handle multiple incoming connections and concurrency is not an issue. It can be used as cache or message broker. Usage as database is not advised by now since data is not being persisted on disk yet.
Table of Contents
Knuckleball is being tested on Linux and OS X. It may be compiled on other systems, perhaps with minor modifications.
libboost-all-dev
, and on OS X you should install the port boost
.libgtest-dev
and follow these steps, and on OS X you should install the port gtest
.$ cmake CMakeLists.txt
$ make
$ make test
To run the server on port 8001 of localhost, type:
$ cd build
$ ./knuckleball --bind 127.0.0.1 --port 8001
To list all the options available, type:
$ ./knuckleball --help
You can use telnet
to play with Knuckleball. A Python client is also available.
The following example shows how to instantiate and manipulate an integer:
$ telnet 127.0.0.1 8001
Integer create: i withValue: 42;
> null
i add: 8;
> null
i get;
> 50
The following example shows how to instantiate and manipulate a vector of integers declared inside a namespace called mynamespace
:
$ telnet 127.0.0.1 8001
Vector<Integer> create: mynamespace::points;
> null
mynamespace::points pushBack: 3;
> null
mynamespace::points pushBack: 7;
> null
mynamespace::points pushBack: 5;
> null
mynamespace::points popFront;
> 3
mynamespace::points get;
> [7,5]
The following example shows how to instantiate and manipulate a set of strings:
$ telnet 127.0.0.1 8001
Set<String> create: players;
> null
players add: "Babe Ruth";
> null
players add: "David Ortiz";
> null
players add: "Paulo Orlando";
> null
players contains? "Jake Arrieta";
> false
players get;
> {"Babe Ruth","David Ortiz","Paulo Orlando"}
The following example shows how to instantiate and manipulate a dictionary that associates floats with strings:
$ telnet 127.0.0.1 8001
Dictionary<String, Float> create: ERAs;
> null
ERAs associateValue: 1.82 withKey: "Ed Walsh";
> null
ERAs associateValue: 2.21 withKey: "Mariano Rivera";
> null
ERAs associateValue: 2.39 withKey: "Clayton Kershaw";
> null
ERAs getValueForKey: "Mariano Rivera";
> 2.210
ERAs get;
> (("Clayton Kershaw",2.390),("Ed Walsh",1.820),("Mariano Rivera",2.210))
Types are divided into:
Booleans are objects that can only represent one of two states: true
or false
.
Boolean create: t withValue: true;
> null
Boolean create: f withValue: false;
> null
t get;
> true
f get;
> false
Boolean createIfNotExists: t withValue: true;
> null
Boolean createIfNotExists: f withValue: false;
> null
t get;
> true
f get;
> false
Boolean create: t withValue: true;
> null
t get;
> true
Boolean create: t withValue: true;
> null
t set: false;
> null
t get;
> false
Boolean create: t withValue: true;
> null
Boolean create: f withValue: false;
> null
t isTrue?;
> true
f isTrue?;
> false
Boolean create: t withValue: true;
> null
Boolean create: f withValue: false;
> null
t isFalse?;
> false
f isFalse?;
> true
Characters are objects that can represent a single character, such as 'a'
or '0'
.
Character create: alphabetic withValue: 'a';
> null
Character create: numeric withValue: '0';
> null
Character create: space withValue: ' ';
> null
alphabetic get;
> 'a'
numeric get;
> '0'
space get;
> ' '
Character createIfNotExists: alphabetic withValue: 'a';
> null
Character createIfNotExists: numeric withValue: '0';
> null
Character createIfNotExists: space withValue: ' ';
> null
alphabetic get;
> 'a'
numeric get;
> '0'
space get;
> ' '
Character create: alphabetic withValue: 'a';
> null
alphabetic get;
> 'a'
Character create: alphabetic withValue: 'a';
> null
alphabetic set: 'z';
> null
alphabetic get;
> 'z'
Character create: alphabetic withValue: 'a';
> null
Character create: numeric withValue: '0';
> null
Character create: space withValue: ' ';
> null
alphabetic isAlphabetic?;
> true
numeric isAlphabetic?;
> false
space isAlphabetic?;
> false
Character create: alphabetic withValue: 'a';
> null
Character create: numeric withValue: '0';
> null
Character create: space withValue: ' ';
> null
alphabetic isNumeric?;
> false
numeric isNumeric?;
> true
space isNumeric?;
> false
Character create: alphabetic withValue: 'a';
> null
Character create: numeric withValue: '0';
> null
Character create: space withValue: ' ';
> null
alphabetic isAlphanumeric?;
> true
numeric isAlphanumeric?;
> true
space isAlphanumeric?;
> false
Character create: alphabetic withValue: 'a';
> null
Character create: numeric withValue: '0';
> null
Character create: space withValue: ' ';
> null
alphabetic isSpace?;
> false
numeric isSpace?;
> false
space isSpace?;
> true
Character create: alphabetic withValue: 'a';
> null
alphabetic isEqualTo? 'a';
> true
alphabetic isEqualTo? 'z';
> false
Character create: alphabetic withValue: 'a';
> null
alphabetic isLessThan? 'z';
> true
alphabetic isLessThan? 'a';
> false
Character create: alphabetic withValue: 'z';
> null
alphabetic isLessThanOrEqualTo? 'z';
> true
alphabetic isLessThanOrEqualTo? 'a';
> false
Character create: alphabetic withValue: 'z';
> null
alphabetic isGreaterThan? 'a';
> true
alphabetic isGreaterThan? 'z';
> false
Character create: alphabetic withValue: 'a';
> null
alphabetic isGreaterThanOrEqualTo? 'a';
> true
alphabetic isGreaterThanOrEqualTo? 'z';
> false
Integers are objects that can represent a whole number value, such as 42
or -42
. Floating-point values, such as 42.5
, can be casted to integers.
Integer create: i withValue: 42;
> null
i get;
> 42
Integer createIfNotExists: i withValue: 42;
> null
i get;
> 42
Integer create: i withValue: 42;
> null
i get;
> 42
Integer create: i withValue: 42;
> null
i set: -42;
> null
i get;
> -42
Integer create: i withValue: 42;
> null
i isEqualTo? 42;
> true
i isEqualTo? 0;
> false
Integer create: i withValue: 0;
> null
i isLessThan? 42;
> true
i isLessThan? 0;
> false
Integer create: i withValue: 42;
> null
i isLessThanOrEqualTo? 42;
> true
i isLessThanOrEqualTo? 0;
> false
Integer create: i withValue: 42;
> null
i isGreaterThan? 0;
> true
i isGreaterThan? 42;
> false
Integer create: i withValue: 0;
> null
i isGreaterThanOrEqualTo? 0;
> true
i isGreaterThanOrEqualTo? 42;
> false
Integer create: i withValue: 42;
> null
i add: 10;
> null
i get;
> 52
Integer create: i withValue: 52;
> null
i subtract: 10;
> null
i get;
> 42
Integer create: i withValue: 10;
> null
i multiplyBy: 4.2;
> null
i get;
> 42
Integer create: i withValue: 42;
> null
i divideBy: 4.2;
> null
i get;
> 10
Floats are objects that can represent a real value, such as 3.1415
or 1e-3
.
Float create: f withValue: 42.0;
> null
Float create: e withValue: 1e-2;
> null
f get;
> 42.000
e get;
> 0.010
Float createIfNotExists: f withValue: 42.0;
> null
Float createIfNotExists: e withValue: 1e-2;
> null
f get;
> 42.000
e get;
> 0.010
Float create: f withValue: 42.0;
> null
f get;
> 42.000
Float create: f withValue: 42.0;
> null
f set: -42.0;
> null
f get;
> -42.000
Float create: f withValue: 42.0;
> null
f isEqualTo? 42.0;
> true
f isEqualTo? 0.0;
> false
Float create: f withValue: 0.0;
> null
f isLessThan? 42.0;
> true
f isLessThan? 0.0;
> false
Float create: f withValue: 42.0;
> null
f isLessThanOrEqualTo? 42.0;
> true
f isLessThanOrEqualTo? 0.0;
> false
Float create: f withValue: 42.0;
> null
f isGreaterThan? 0.0;
> true
f isGreaterThan? 42.0;
> false
Float create: f withValue: 0.0;
> null
f isGreaterThanOrEqualTo? 0.0;
> true
f isGreaterThanOrEqualTo? 42.0;
> false
Float create: f withValue: 42.0;
> null
f add: 10.0;
> null
f get;
> 52.000
Float create: f withValue: 52.0;
> null
f subtract: 10.0;
> null
f get;
> 42.000
Float create: f withValue: 4.2;
> null
f multiplyBy: 10.0;
> null
f get;
42.000;
Float create: f withValue: 42.0;
> null
f divideBy: 4.2;
> null
f get;
> 10.000
Strings are objects that can represent a sequence of characters, such as "knuckleball"
.
String create: str;
> null
str get;
> ""
String createIfNotExists: str;
> null
str get;
> ""
String create: str withValue: "knuckleball";
> null
str get;
> "knuckleball"
String createIfNotExists: str withValue: "knuckleball";
> null
str get;
> "knuckleball"
String create: str withValue: "knuckleball";
> null
str get;
> "knuckleball"
String create: str withValue: "";
> null
str set: "knuckleball";
> null
str get;
> "knuckleball"
String create: str withValue: "";
> null
str isEmpty?;
> true
str concatenate: "knuckleball";
> null
str isEmpty?;
> false
String create: str withValue: "knuckleball";
> null
str startsWith? "knuckle";
> true
str startsWith? "ball";
> false
String create: str withValue: "knuckleball";
> null
str endsWith? "ball";
> true
str endsWith? "knuckle";
> false
String create: str withValue: "knuckleball";
> null
str isLexicographicallyEqualTo? "knuckleball";
> true
str isLexicographicallyEqualTo? "";
> false
String create: str withValue: "";
> null
str isLexicographicallyLessThan? "knuckleball";
> true
str isLexicographicallyLessThan? "";
> false
String create: str withValue: "knuckleball";
> null
str isLexicographicallyLessThanOrEqualTo? "knuckleball";
> true
str isLexicographicallyLessThanOrEqualTo? "";
> false
String create: str withValue: "knuckleball";
> null
str isLexicographicallyGreaterThan? "";
> true
str isLexicographicallyGreaterThan? "knuckleball";
> false
String create: str withValue: "";
> null
str isLexicographicallyGreaterThanOrEqualTo? "";
> true
str isLexicographicallyGreaterThanOrEqualTo? "knuckleball";
> false
String create: str withValue: "knuckleball";
> null
str length;
> 11
String create: str withValue: "knuckleball";
> null
str atIndex: 0;
> 'k'
String create: str withValue: "knuckleball";
> null
str first: 7;
> "knuckle"
String create: str withValue: "knuckleball";
> null
str last: 4;
> "ball"
String create: str withValue: "knuckleball";
> null
str substringFromIndex: 7;
> "ball"
String create: str withValue: "knuckleball";
> null
str substringFromIndex: 0 toIndex: 7;
> "knuckle"
String create: str withValue: "knucklebal";
> null
str pushBack: 'l';
> null
str get;
> "knuckleball"
String create: str withValue: "nuckleball";
> null
str pushFront: 'k';
> null
str get;
> "knuckleball"
String create: str withValue: "knuckleball";
> null
str popBack;
> 'l'
str get;
> "knucklebal"
String create: str withValue: "knuckleball";
> null
str popFront;
> 'k'
str get;
> "nuckleball"
String create: str withValue: "knuckleball";
> null
str popAtIndex: 2;
> 'u'
str get;
> "knckleball"
String create: str withValue: "knuckle";
> null
str concatenate: "ball";
> null
str get;
> "knuckleball"
String create: str withValue: "knkleball";
> null
str insert: "uc" beforeIndex: 2;
> null
str get;
> "knuckleball"
String create: str withValue: "knuckleball";
> null
str eraseFromIndex: 7;
> null
str get;
> "knuckle"
String create: str withValue: "knuckleball";
> null
str eraseFromIndex: 7 toIndex: 9;
> null
str get;
> "knucklell"
String create: str withValue: "knuckleball";
> null
str clear;
> null
str get;
> ""
Vectors are containers that store elements using contiguous storage locations.
Vector<Integer> create: points;
> null
points get;
> []
Vector<Integer> createIfNotExists: points;
> null
points get;
> []
Vector<Integer> create: points;
> null
points get;
> []
Vector<Integer> create: points;
> null
points isEmpty?;
> true
points pushBack: 42;
> null
points isEmpty?;
> false
Vector<Integer> create: points;
> null
points contains? 42;
> false
points pushBack: 42;
> null
points contains? 42;
> true
Vector<Integer> create: points;
> null
points pushBack: 3;
> null
points pushBack: 7;
> null
points pushBack: 5;
> null
points contains? 7 fromIndex: 0;
> true
points contains? 7 fromIndex: 2;
> false
Vector<Integer> create: points;
> null
points pushBack: 3;
> null
points pushBack: 7;
> null
points pushBack: 7;
> null
points count: 7;
> 2
Vector<Integer> create: points;
> null
points pushBack: 3;
> null
points pushBack: 5;
> null
points pushBack: 7;
> null
points atIndex: 0;
> 3
Vector<Integer> create: points;
> null
points pushBack: 3;
> null
points pushBack: 5;
> null
points pushBack: 3;
> null
points pushBack: 5;
> null
points firstIndexOf: 5;
> 1
Vector<Integer> create: points;
> null
points pushBack: 3;
> null
points pushBack: 5;
> null
points pushBack: 3;
> null
points pushBack: 5;
> null
points firstIndexOf: 3 fromIndex: 1;
> 2
Vector<Integer> create: points;
> null
points pushBack: 3;
> null
points pushBack: 5;
> null
points pushBack: 3;
> null
points allIndexesOf: 3;
> [0,2]
Vector<Integer> create: points;
> null
points pushBack: 3;
> null
points pushBack: 5;
> null
points pushBack: 7;
> null
points size;
> 3
Vector<Integer> create: points;
> null
points pushBack: 3;
> null
points pushBack: 5;
> null
points pushBack: 7;
> null
points first: 2;
> [3,5]
Vector<Integer> create: points;
> null
points pushBack: 3;
> null
points pushBack: 5;
> null
points pushBack: 7;
> null
points last: 2;
> [5,7]
Vector<Integer> create: points;
> null
points pushBack: 3;
> null
points pushBack: 5;
> null
points pushBack: 7;
> null
points pushBack: 9;
> null
points sliceFromIndex: 2;
> [7,9]
Vector<Integer> create: points;
> null
points pushBack: 3;
> null
points pushBack: 5;
> null
points pushBack: 7;
> null
points pushBack: 9;
> null
points sliceFromIndex: 1 toIndex: 3;
> [5,7]
Vector<Integer> create: points;
> null
points pushBack: 3;
> null
points pushBack: 5;
> null
points pushBack: 7;
> null
points get;
> [3,5,7]
Vector<Integer> create: points;
> null
points pushFront: 3;
> null
points pushFront: 5;
> null
points pushFront: 7;
> null
points get;
> [7,5,3]
Vector<Integer> create: points;
> null
points pushBack: 3;
> null
points pushBack: 5;
> null
points pushBack: 7;
> null
points popBack;
> 7
points get;
> [3,5]
Vector<Integer> create: points;
> null
points pushBack: 3;
> null
points pushBack: 5;
> null
points pushBack: 7;
> null
points popFront;
> 3
points get;
> [5,7]
Vector<Integer> create: points;
> null
points pushBack: 3;
> null
points pushBack: 5;
> null
points pushBack: 7;
> null
points popAtIndex: 1;
> 5
points get;
> [3,7]
Vector<Integer> create: points;
> null
points pushBack: 3;
> null
points pushBack: 7;
> null
points insert: 5 beforeIndex: 1;
> null
points get;
> [3,5,7]
Vector<Integer> create: points;
> null
points pushBack: 3;
> null
points pushBack: 5;
> null
points pushBack: 7;
> null
points eraseFromIndex: 1;
> null
points get;
> [3]
Vector<Integer> create: points;
> null
points pushBack: 3;
> null
points pushBack: 5;
> null
points pushBack: 7;
> null
points eraseFromIndex: 1 toIndex: 2;
> null
points get;
> [3,7]
Vector<Integer> create: points;
> null
points pushBack: 3;
> null
points pushBack: 5;
> null
points pushBack: 3;
> null
points pushBack: 5;
> null
points removeFirst: 5;
> null
points get;
> [3,3,5]
Vector<Integer> create: points;
> null
points pushBack: 3;
> null
points pushBack: 5;
> null
points pushBack: 3;
> null
points pushBack: 5;
> null
points removeFirst: 5 fromIndex: 2;
> null
points get;
> [3,5,3]
Vector<Integer> create: points;
> null
points pushBack: 3;
> null
points pushBack: 5;
> null
points pushBack: 3;
> null
points pushBack: 5;
> null
points removeAll: 3;
> null
points get;
> [5,5]
Vector<Integer> create: points;
> null
points pushBack: 3;
> null
points pushBack: 5;
> null
points pushBack: 3;
> null
points pushBack: 5;
> null
points replaceFirst: 5 with: 7;
> null
points get;
> [3,7,3,5]
Vector<Integer> create: points;
> null
points pushBack: 3;
> null
points pushBack: 5;
> null
points pushBack: 3;
> null
points pushBack: 5;
> null
points replaceFirst: 5 fromIndex: 2 with: 7;
> null
points get;
> [3,5,3,7]
Vector<Integer> create: points;
> null
points pushBack: 3;
> null
points pushBack: 5;
> null
points pushBack: 3;
> null
points pushBack: 5;
> null
points replaceAll: 5 with: 7;
> null
points get;
> [3,7,3,7]
Vector<Integer> create: points;
> null
points pushBack: 7;
> null
points pushBack: 3;
> null
points pushBack: 5;
> null
points sort;
> null
points get;
> [3,5,7]
Vector<Integer> create: points;
> null
points pushBack: 3;
> null
points pushBack: 5;
> null
points pushBack: 7;
> null
points reverse;
> null
points get;
> [7,5,3]
Vector<Integer> create: points;
> null
points pushBack: 3;
> null
points pushBack: 5;
> null
points pushBack: 7;
> null
points clear;
> null
points get;
> []
Sets are containers that store unique elements.
Set<String> create: players;
> null
players get;
> {}
Set<String> createIfNotExists: players;
> null
players get;
> {}
Set<String> create: players;
> null
players get;
> {}
Set<String> create: players;
> null
players isEmpty?;
> true
players add: "Babe Ruth";
> null
players isEmpty?;
> false
Set<String> create: players;
> null
players contains? "Babe Ruth";
> false
players add: "Babe Ruth";
> null
players contains? "Babe Ruth";
> true
Set<String> create: players;
> null
players add: "Babe Ruth";
> null
players add: "David Ortiz";
> null
players add: "Paulo Orlando";
> null
players size;
> 3
Set<String> create: players;
> null
players add: "Babe Ruth";
> null
players get;
> {"Babe Ruth"}
Set<String> create: players;
> null
players add: "Babe Ruth";
> null
players remove: "Babe Ruth";
> null
players get;
> {}
Set<String> create: players;
> null
players add: "Babe Ruth";
> null
players add: "David Ortiz";
> null
players add: "Paulo Orlando";
> null
players clear;
> null
players get;
> {}
Dictionaries are associative containers that store keys and their associated values.
Dictionary<String, Float> create: ERAs;
> null
ERAs get;
> ()
Dictionary<String, Float> createIfNotExists: ERAs;
> null
ERAs get;
> ()
Dictionary<String, Float> create: ERAs;
> null
ERAs get;
> ()
Dictionary<String, Float> create: ERAs;
> null
ERAs isEmpty?;
> true
ERAs associateValue: 1.82 withKey: "Ed Walsh";
> null
ERAs isEmpty?;
> false
Dictionary<String, Float> create: ERAs;
> null
ERAs containsKey? "Ed Walsh";
> false
ERAs associateValue: 1.82 withKey: "Ed Walsh";
> null
ERAs containsKey? "Ed Walsh";
> true
Dictionary<String, Float> create: ERAs;
> null
ERAs size;
> 0
ERAs associateValue: 1.82 withKey: "Ed Walsh";
> null
ERAs size;
> 1
Dictionary<String, Float> create: ERAs;
> null
ERAs associateValue: 1.82 withKey: "Ed Walsh";
> null
ERAs associateValue: 2.21 withKey: "Mariano Rivera";
> null
ERAs associateValue: 2.39 withKey: "Clayton Kershaw";
> null
ERAs keys;
> ["Clayton Kershaw","Ed Walsh","Mariano Rivera"]
Dictionary<String, Float> create: ERAs;
> null
ERAs associateValue: 1.82 withKey: "Ed Walsh";
> null
ERAs associateValue: 2.21 withKey: "Mariano Rivera";
> null
ERAs associateValue: 2.39 withKey: "Clayton Kershaw";
> null
ERAs values;
> [2.390,1.820,2.210]
Dictionary<String, Float> create: ERAs;
> null
ERAs associateValue: 1.82 withKey: "Ed Walsh";
> null
ERAs getValueForKey: "Ed Walsh";
> 1.820
Dictionary<String, Float> create: ERAs;
> null
ERAs associateValue: 1.82 withKey: "Ed Walsh";
> null
ERAs get;
> (("Ed Walsh",1.82))
Dictionary<String, Float> create: ERAs;
> null
ERAs associateValue: 1.82 withKey: "Ed Walsh";
> null
ERAs removeKey: "Ed Walsh";
> null
ERAs get;
> ()
Dictionary<String, Float> create: ERAs;
> null
ERAs associateValue: 1.82 withKey: "Ed Walsh";
> null
ERAs associateValue: 2.21 withKey: "Mariano Rivera";
> null
ERAs associateValue: 2.39 withKey: "Clayton Kershaw";
> null
ERAs clear;
> null
ERAs get;
> ()
Context is an execution environment.
Boolean create: std::bool withValue: true;
> null
Integer create: mynamespace::i withValue: 42;
> null
Context listNamespaces;
> [mynamespace,std]
Boolean create: std::bool withValue: true;
> null
Integer create: i withValue: 42;
> null
Context listVariables;
> [i,std::bool]
Boolean create: std::bool withValue: true;
> null
Character create: std::char withValue: 'a';
> null
Integer create: mynamespace::i withValue: 42;
> null
Context listVariablesOfNamespace: std;
> [std::bool,std::char]
Boolean create: bool withValue: true;
> null
Integer create: i withValue: 42;
> null
Context deleteVariable: bool;
> null
Context listVariables;
> [i]
Boolean create: std::bool withValue: true;
> null
Character create: std::char withValue: 'a';
> null
Integer create: i withValue: 42;
> null
Context deleteVariablesOfNamespace: std;
> null
Context listVariables;
> [i]
Context setFloatPrecision: 5;
> null
Context getFloatPrecision;
> 5
Float create: f withValue: 0.1;
> null
Context setFloatPrecision: 5;
> null
f get;
> 0.10000
Context setFloatComparisonTolerance: 1e-3;
> null
Context getFloatComparisonTolerance;
> 0.001
Float create: f withValue: 0.0;
> null
Context setFloatComparisonTolerance: 1.0;
> null
f isEqualTo? 0.9;
> true
Context setFloatComparisonTolerance: 1e-3;
> null
f isEqualTo? 0.9;
> false
Connection is an object that represents the TCP connection with the server.
Connection authenticateWithPassword: "password";
> null
Connection close;
> null