Runtime components, creates open and secure integrated library
for application development(like NextStep.CoreFoundation for POSIX + winAPI).
ONLY 120 KB 4all, CARL!
Use RayConfig.h to reduce size to 100KB, by removing warnings and error strings.
Can be compiled to use only CoreObjects like strings and containers using RAY_EMBEDDED 82KB!
Ray additions to C language defines some C-based syntax,
that makes object-oriented life easier for C developers.
All based on defines and can use diff code style (RSyntax.h).
- Array, List - NSArray, std::vector, list analog
- Dictionary - NSDictionary, std::map analog
- Buffer - store full copy of objects
- Data - base sized data class for strings, and bytes
- Wide range of string processing operations (RString)
- Replacings
- Find of substring or symbol
- Delete characters/substrings
- Delete of duplications characters/substring
- Compares
- Read from file/ apend to file
- Tokenization into container Array
- Base64 encoding/decoding
- etc...
- RThread and RThreadPool
- RSocket (WINAPI + Berkley)
- RTCPHandler - multi-threaded tcp server engine
- Easy sandboxing and testing with logging
- Memory management with RAutoPool (Checking leaks, manage allocations)
- Work with byte buffers and memory chunks
- Simple VM with Brainfuck compiler and execution visualization in Curses
- Simple TCP multi-threaded text-chat with 'nc' util client
Work with RArray:
#include <RayFoundation.h>
typedef struct ComplexStruct {
size_t id;
RString *fullName;
} ComplexStruct;
void printComplexStruct(ComplexStruct *some) {
printf("%p | id: %02lu | fullname : \'%s\' \n", some, some->id, some->fullName->baseString);
}
void complexDeleter(ComplexStruct *some) {
deleter(some->fullName, RString);
free(some);
}
int main(int argc, const char *argv[]) {
size_t iterator;
RArray *array = makeRArray(); // create array
// sets delegates for automatic print and cleanup
array->printerDelegate = (PrinterDelegate) printComplexStruct;
array->destructorDelegate = (DestructorDelegate) complexDeleter;
forAll(iterator, 100) {
// create struct and add to array
ComplexStruct *some = malloc(sizeof(ComplexStruct));
some->id = iterator + 1;
some->fullName = stringWithFormat("Object # %lu", iterator + 1); // more string processing API in RString.h
$(array, m(addObject, RArray)), some);
}
// print
printerOfRArray(array);
// delete, automatically calls destructor delegate and free array prt
deleter(array, RArray);
// some syntaxic sugar see initFromArray, initFromArrayWithSizes, arrayFromArray
// create array of strings
RString *uniqTok = RS("Unique token");
array = RA(RS("Token 1"), RS("Token 2"), uniqTok, nil); // must be NULL terminated
array->printerDelegate = (PrinterDelegate) p(RString);
array->destructorDelegate = free;
printerOfRArray(array);
RCompareDelegate delegate;
delegate.etaloneObject = uniqTok;
delegate.virtualCompareMethod = (RCompareFlags (*)(pointer, pointer)) compareWithRString;
RFindResult result = findObjectWithDelegateRArray(array, &delegate); // search
if(result.object != nil) { // object != nil -> found object, place also logged
printf("Found some object at place %lu!\n", result.index);
} else {
printf("Object not found!\n");
}
RArray *subarray = getSubarrayRArray(array, makeRRange(1, 2)); // delegates will be copied
printerOfRArray(subarray);
subarray->destructorDelegate = nil; // not want to delete strings
deleter(subarray, RArray);
deleter(array, RArray); // cleanup strings
return 0;
}
RDictionary use:
#include <RayFoundation.h>
#include "Tests.h"
int main(int argc, const char *argv[]) {
enablePool(RPool);
ComplexTest();
RDictionary *dict = dictionaryFromPairs("key", "value",
"key2", "value2",
"key3", "value3",
"key4", "value4",
"key5", "value5",
nil);
char * string = $(dict, m(getObjectForKey, RDictionary)), "key4");
printf("Found object for \'key4\' - \'%s\' \n\n", string);
deleter(dict, RDictionary);
endRay(); // standart cleanup
}
BrainFuck samples:
#include "RayFoundation/RayFoundation.h"
#include "RVirtualMachine/RVirtualFunction/RVirtualFunction.h"
#include "RVirtualMachine/RVirtualMachine/RVirtualMachine.h"
#include "RVirtualMachine/RVirtualCompiler.h"
int main(int argc, const char *argv[]) {
// ezy brainfuck hello world
RVirtualFunction *function = $(RVC, m(createFunctionFromBrainFuckSourceCode, RVirtualCompiler)),
RS(" My brainfuck hello world : +++++++++++++++++++++++++++++++++++++++++++++\n"
" +++++++++++++++++++++++++++.+++++++++++++++++\n"
" ++++++++++++.+++++++..+++.-------------------\n"
" ---------------------------------------------\n"
" ---------------.+++++++++++++++++++++++++++++\n"
" ++++++++++++++++++++++++++.++++++++++++++++++\n"
" ++++++.+++.------.--------.------------------\n"
" ---------------------------------------------\n"
" ----.-----------------------."));
// execute of byte-code on RVM singleton
executeRay(function);
$(function, d(RVirtualFunction)) );
// brainfuck compiler multiple-cycles test
function = $(RVC, m(createFunctionFromBrainFuckSourceCode, RVirtualCompiler)),
RS(" Cycles : +++ [ > +++ [.-] <-]")); // prints '03 02 01' 3-times
executeRay(function);
$(function, d(RVirtualFunction)) );
// brainfuck hard(with [, ]) hello world on RVM
function = $(RVC, m(createFunctionFromBrainFuckSourceCode, RVirtualCompiler)),
RS(" Hard Hello world : ++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++\n"
" .>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.\n"
" ------.--------.>+.>."));
// rasm byte-code print in words
$(function, p(RVirtualFunction)) );
executeRay(function);
$(function, d(RVirtualFunction)) );
// final function delete
deallocator(function);
// RVM singleton cleanup
deleteRVM();
endRay(); // standart cleanup
}
RAutoPool:
int main(int argc, const char *argv[]) {
initPointers();
enablePool(RPool); // enable pool sinleton
ComplexTest(); // do something
$(RPool, p(RAutoPool))); // check leaks
deleter(RPool, RAutoPool); // total cleanup
return 0;
// or use macro endRay -> standart cleanup
}
Work with RClassTable:
#include "RayFoundation/RClassTable/RClassTable.h"
void RClassTableTest(void){
// register class name once, and get identifier in result
// it's can be used like management tool for creating unique
// identifiers for string objects (in our case class names)
registerClassOnce("Luke");
// print our class table
printRCTS;
registerClassOnce("Dart");
printRCTS;
registerClassOnce("Leia");
printRCTS;
// try once more, but here is only one record
registerClassOnce("Leia");
registerClassOnce("Dart");
registerClassOnce("Luke");
registerClassOnce("Han Solo");
printRCTS;
// get Identifier of Han Solo
char *checkName = "Han Solo";
RPrintf("Identifier of %s is - %qu \n", checkName, registerClassOnce(checkName));
// flush your class table
flushRCTS;
printRCTS;
// delete your class table
releaseRCTS;
// use not singleton
RClassTable *table = makeRCTable();
$(table, m(registerClassWithName, RClassTable)), "Some string");
$(table, m(registerClassWithName, RClassTable)), "Some string2");
$(table, m(registerClassWithName, RClassTable)), "Some string3");
// once more time, to check
$(table, m(registerClassWithName, RClassTable)), "Some string3");
$(table, p(RClassTable)) );
$(table, d(RClassTable)) );
deallocator(table);
}
You can simply use it in Yours C++ projects:
#include <iostream>
#include "RayFoundation.h"
using namespace std;
class MyClass{
protected:
double x;
double y;
public:
MyClass(){
}
~MyClass(){
}
void Print(){
cout << "MyClass obj - " << this << endl;
}
};
void deleter(pointer src) {
delete (MyClass*)src;
}
void Printer(pointer src){
((MyClass*)src)->Print();
}
int main(int argc, const char *argv[]) {
RArray *helloArray = makeRArray();
helloArray->destructorDelegate = deleter;
helloArray->printerDelegate = Printer;
for(unsigned i = 0; i < 100000; ++i) {
MyClass *a = new MyClass;
addObjectRArray(helloArray, a);
}
$(helloArray, p(RArray)));
deleteRA(helloArray);
return 0;
}
Some multi-thread tcp-echo server sample on RTCPHandler:
#include <RayFoundation/RayFoundation.h>
#include "Tests.h"
#define BUFFER_SIZE 1500
pointer exec(RTCPDataStruct *data) {
char buffer[BUFFER_SIZE];
const char *address = addressToString(&data->socket->address);
ushort port = ntohs(data->socket->address.sin_port);
unsigned currentThread = (unsigned int) currentThreadIdentifier();
byte resultFlag;
size_t receivedSize;
RPrintf("[I] %s:%u connected [tuid : %u]\n", address, port, currentThread);
$(data->socket, m(sendString, RSocket)), RS("Hello from RServer.\n"));
resultFlag = $(data->socket, m(receive, RSocket)), buffer, 1000, &receivedSize);
while(resultFlag != networkConnectionClosedConst) {
buffer[receivedSize] = 0;
RPrintf("%s:%u[%u] > %s", address, port, currentThread, buffer);
$(data->socket, m(send, RSocket)), buffer, receivedSize);
resultFlag = $(data->socket, m(receive, RSocket)), buffer, BUFFER_SIZE, &receivedSize);
}
RPrintf("[I] %s:%u disconnected [tuid : %u]\n", address, port, currentThread);
deleter(data->socket, RSocket);
data->socket = nil; // for auto-cleaning
return nil;
}
RTCPHandler *server = nil;
RTCPDelegate *delegate = nil;
void startServer(void) {
server = c(RTCPHandler)(nil);
if(server != nil) {
delegate = allocator(delegate);
if(delegate != nil) {
delegate->delegateFunction = (RThreadFunction) exec;
delegate->context = server;
$(server, m(set_delegate, RTCPHandler)), delegate);
RPrintf("RTCPHandler starting %p\n", server);
$(server, m(startOnPort, RTCPHandler)), 4000);
}
}
}
int main(int argc, const char *argv[]) {
rbool closeAll = no;
byte connectionState;
char buffer[BUFFER_SIZE];
const char *address;
ushort port;
RSocket *configurator;
size_t receivedSize;
enablePool(RPool);
ComplexTest(); // lib test
startServer();
configurator = openListenerOnPort(4001, 10);
if(configurator == nil) goto exit;
while(!closeAll) {
RSocket *current = $(configurator, m(accept, RSocket)));
address = addressToString(¤t->address);
port = ntohs(current->address.sin_port);
RPrintf("[I] Configurator %s:%u connected\n", address, port);
connectionState = networkOperationSuccessConst;
while(connectionState != networkConnectionClosedConst) {
connectionState = $(current, m(receive, RSocket)), buffer, BUFFER_SIZE, &receivedSize);
if(connectionState == networkOperationSuccessConst) {
if(receivedSize > 8) {
buffer[receivedSize] = 0;
ifMemEqual(buffer, "secretkey", 9) {
ifMemEqual(buffer + 10, "shutdown", 8) {
$(current, m(sendString, RSocket)), RS("Server will terminate\n"));
RPrintf("[I] Will terminate with command from %s:%u\n\n", address, port);
closeAll = yes;
}
ifMemEqual(buffer + 10, "system", 6) {
RPrintf(">> Execute %s", buffer + 17);
system(buffer + 17);
}
} else {
RPrintf("[E] Bad user key on %s:%u\n", address, port);
}
}
connectionState = networkConnectionClosedConst;
} else if (connectionState == networkOperationErrorConst) {
RError2("[E] Receive on configurator connection, from %s:%u", current, address, port);
}
}
deleter(current, RSocket);
}
deleter(configurator, RSocket);
deallocator(delegate);
p(RTCPHandler)(server);
$(server, m(terminate, RTCPHandler)));
deleter(server, RTCPHandler);
exit:
endSockets();
endRay();
}