Portfolio

c′ ( 2024 )

C Prime is a new language very close related to C, C Prime is an very simple addition to c, You could say c prime is c with classes without the bloat. Also unique about C Prime is the C Prime compiler, Because the C Prime compiler will convert your C Prime code to readable, high-performance C code. This code can than be compiled with a normal C compiler.

As c compiler i use the tiny c compiler. The C Prime Preprocessor can be compiled using the tiny c compiler using Musl or Gnu libc. Also your preprocessed code can be compiled using the Tiny c compiler.

Then you can preprocess your Object Oriented c code using the compiled binary. This will generate a folder with readable c files. These can then be compiled using the tiny c compiler.

Compiling the C Prime preprocessor takes only a few milliseconds. and using the C Prime preprocessor to preprocess your object oriented c code to pure c also takes a few milliseconds. It is almost instantaneous. Then compiling your resulting c code with the tiny c compiler takes somewhat longer. still less then 1 second.

Year 2024
Author Kaj Dijkstra
Languages C
Frameworks None
Size of Sourc code 200kb
Size of Binary 93.8kb
Lines of code 9 588

Classes

Creating simple classes.


#include "console.h"

class application{

	sayHi( char * name ) {

		console.log( "Hi ", name );

	}

	launch() {

		this->sayHi( "John" );

	}

}

void main() {

	application * instance = new application();

	instance->launch();

}


Constructors

Instantiate a class using an constructor.



class vector3{

	float x;

	float y;

	float z;

	constructor( float x, float y, float z ) {

		this->x = x;

		this->y = y;

		this->z = z;

	}

	display() {

		printf("x: %f, y: %f, z: %f", this->x, this->y, this->z);

	}

}

void main() {

	vector3 * a = new vector3( 1.0, 0.0, 1.0 );

	a->display();

}


Running a webserver

For example to setup a server you can write:



#include "../http.h"

#include "./fileSystem.h"

#include "./text.h"

#include "./mimeTypes.h"


void handleRequest( struct request * requestInstance, struct text * response ) {

	text * filePath			= new text("www/");

	filePath				+= requestInstance->url;

	// Request information
	printf("server address:	[%s:%u]\n", 	requestInstance->address, requestInstance->port );

	printf("mimeType:		%-30s \n", 	requestInstance->mimeType);

	printf("header:		%-30s \n",			requestInstance->extension );

	printf("method:		%-30s		 \n", 	requestInstance->method );

	printf("version:		%-30s		 \n\n", requestInstance->version );

	if( filesystem->exists( filePath->value ) ) {

		text * content 		= filesystem->readFile( filePath->value, "binary" );

		response			+= "HTTP/1.0 200 OK\r\n";

		response			+= "Server: webserver-c\r\n";

		response			+= "Content-type: " + requestInstance->mimeType + "\r\n\r\n";

		response			+= "Simple test server\r\n";
		//response->appendObject( content );

		free( content );

	} else {

		printf("file does not exists...		%s\n", filePath->value);

	}


}

void main() {
	
	http * serverInstance = new http();

	serverInstance->createServer( handleRequest );

	serverInstance->listen( 8080 );

}


after initializeOpenSSL socket created successfully socket successfully bound to address server listening for connections

Manipulating files

To handle your files you could write:




#include "../fileSystem.h"

#include "../console.h"

void main() {
	
	char * directory2			= "./assets/";

	fileSystem * filesystem 	= new fileSystem();

	char * directory			= "./assets/";



	filesystem->writeFile( "./assets/testFile", "content of file" );


	array * files 				= filesystem->readDir( directory );

	int fileCount 				= files->length();

	for ( int i = 0; i < fileCount; ++i )
	{

		char * filename = files->get( i );

		char * path		= directory->concatenate( filename );

		char * source 	= filesystem->readFile( path );


		printf("filename: 	%s\n", path);

		printf("source: 	%s\n\n\n", source);

	}

	if( filesystem->ensureDirectory("./Some/example/assure") ) {

		console.log("Directories successfuly created.");

	}

	if( filesystem->exists( "Some" ) ) {

		console.log("Directories 'Some' does exist.");

	}

}

void abort() {


}
filename: ./assets/test source: this is just a test. filename: ./assets/testFile source: content of file Directories successfuly created. Directories 'Some' does exist.

Extending classes

You can extend one or more classes. This will overide the methods and properties, with the methods and properties of the extended class.



#include "stdio.h"  

class classB{

	int propertyA = 1;

	void test() {

		printf("%s\n", this->propertyA );

	}

}

class classA{

	int propertyA = 2;

	void test() {

		printf("%s\n", this->propertyA );

	}

}


class inherit extends classB, classA{

	int propertyA = 3;

	void test() {

		printf("%s\n", this->propertyA );

	}

}


#include 

#include "extends.h"

void main() {

	struct inherit * pointer 	= new inherit();

	for (int i = 0; i < 10; ++i)
	{

		struct inherit instance = new inherit();

		instance.propertyA = i;

		instance.test();

	}

}

Console.log

You can print all class instances and arrays using console.log. This is all possible because of datatype overloading and automatic reflection.

Reflection means that the structure of the class is always available at runtime.



#include "../console.h"

#include "../street.h"

#include "../user.h"

#include "../array.h"



void main() {
	
	struct user	* newUser		= new user();

	newUser->id		= 1;

	newUser->username	= "peter";

	newUser->userlevel	= 2134;

	newUser->hash		= "#234234325";



	struct array * addresses = newUser->addresses;


	address * someAddress = new address();

	someAddress->street = "HiLane";

	someAddress->number	= 1234;

	addresses->add( someAddress );




	address * otherAddress = new address();

	otherAddress->street = "OtherLane";

	otherAddress->number	= 4567;

	addresses->add( otherAddress );

	// todo   newUser->addresses->add( otherAddress );


	printf("adresses count: %i\n\n", addresses->length() );


	char * something 	= "this is from an char * ";

	int somethingElse	= 123;


	console.log( 	"Goedendag", 
					123456, 
					"en een andere text.", 
					something, 
					somethingElse, 
					"something en something", 
					"in native c", 
					23456, 
					newUser, 
					"and some text again" );

}

void abort() {

	
}

adresses count: 2 Goedendag 123456 en een andere text. this is from an char * 123 something en something in native c 23456 user : { username : peter id : 1 userlevel : 2134 hash : #234234325 addresses : address : { street : HiLane number : 1234 } address : { street : OtherLane number : 4567 } } and some text again

Datatype overloading

This demostrates how an datatype can be accessed within the called method when using argument overload.


class console{

	void log( ... ) {

		va_list args;

		va_start( args, count );

		//printf("count: %i\n\n", count);

		for (int i = 0; i < count; ++i)
		{
			int datatype 		= datatypes[i]; // va_arg_type( argumentIndex )

			// this will print the datatype of the argument
			printf("datatype %i\n", datatype);

			if( datatype == 1 ) {

				// do something

			}


			printf(" ");

		}

		printf("\n");

		va_end( args);

	}

}

Operator overload

With operator overload you can manipulate your class instances using operators.


class vector2{

	int x = 123;

	int y = 234;

	constructor( int x, int y ) {

		this->x = x;

		this->y = y;

	}

	vector2 * operator+( vector2 * b ){

		this->add( b );

		return this;

	}

	vector2 * operator+=( struct vector2 * b ) {

		this->add( b );

		return this;

	}
	
	add( vector2 * a ) {

		this->x += a->x;

		this->y += a->y;

		addition( this->y, a->x );

	}

}
Then you can use those classes like this:



#include "../text.h"

#include "../vector2.h"

#include "../vector3.h"

#include "../console.h"



void main() {

	text * textB			= new text("ook mooi");

	char * other			= malloc(5000);

	vector3 * newVector3 	= new vector3();

	newVector3->x	= 2;

	newVector3->y	= 2;

	newVector3->z	= 3;


	for (int i = 0; i < 1000; ++i)
	{

		vector3 * vector3B 	= new vector3();


		vector3B->x	= 2;

		vector3B->y	= 3;

		vector3B->z	= 4;


		vector3 * vector3C = new vector3();


		vector3C->x	= 2;

		vector3C->y	= 3;

		vector3C->z	= 4;

		newVector3	= vector3C + ( vector3C + newVector3 + ( ( ( ( vector3B + vector3C ) ) + vector3C ) + vector3B ) );

		newVector3	= newVector3 + ( ( vector3B + vector3C ) + vector3C );

	}

	console->log( newVector3 );

	text * textA		= new text("mooi");
	
	if( textA == textB ) {

		printf("mooi zo");

	}

	text * textC		= new text("mooi");

	text * textD		= new text("mooi");

	
	if( ( ( textA == textC ) && ( textA == textD ) ) && textA == textD ) {

		printf("Good, This works.\n\n");

	}

	char * realChar = "something";

	if( "something" == realChar ) {

		printf("Great.\n\n");

	}

	if( realChar == "something" ) {

		printf("Great.\n\n");

	}

	if( realChar == realChar ) {

		printf("Great.\n\n");

	}

	if( "something" == "something" && realChar == "something" ) {

		printf("Great.\n\n");

	}


// Easy concatenation

	char * fancy	= "aaa ";

	char * aaaa		= " bbb ";

	char * bbbb		= " ccc ";

	char * dddd		= " dddd ";

	other += ( fancy + ( bbbb +  aaaa ) + dddd ) + " eee" + " het is een wonder ";

	other += ("boven wonder" + returnText("this is a normal function") + " and this " + ( "works just good..." + dddd )); 

	other += "something" +  ( returnText("this is a normal function") + textB->toNative() + textB->value );

	other +=  ("and here some text") + (textB->toNative()) ;

	other +=  (  textB->value + ( ( textB->value ) + returnText("this is a normal function") ) + (textB->toNative() + "here some text" + textB->value ) );

	other +=  textB->value + textB->value + ( textB->value + textB->value ) +  ( textB->value + textB->value ) + textB->value + textB->value;

	console.log( "Great ", other );









	vector2 testVector 		= new vector2( 1,  450 );


	//int count = 0;

	for (int i = 0; i < 2000000; ++i)
	{
		vector2  testVector1		= new vector2( 2,  450 );

		vector2 *  testVector2 		= new vector2( 10, 450 );

		testVector					+=  testVector1 + testVector2;

	}

}


char * returnText( char * text ) {

	return text;

}

void abort() {


}

Sqlite3

Using these features C Prime also provides an simplistic sqlite3 class.


#include "../sqlite.h"

#include "../array.h"

#include "../console.h"

#include "../street.h"

#include "../user.h"

#include "time.h"

void main() {
	
	// sqlite * sql 				= new sqlite("./database/users.sqlite");

	sqlite * sql 				= new sqlite(":memory:");

	sql->selectModel( "user" );


	sql->createTable();

	char * names[20]			= { "piet", "gurbe", "siebe", "gerben", "twain", "piet", "gurbe", "siebe", "gerben", "twain", "piet", "gurbe", "siebe", "gerben", "twain" };

	clock_t tic 				= clock();


	array * usersInsertArray 	= new array();

	for (int i = 0; i <10; ++i) //20000
	{
	
		char * name = names[i];

		struct user * userInstance = new user();

		userInstance->id		= i;

		userInstance->username 	= name;

		userInstance->userlevel	= 3;

		userInstance->hash		= "12345";

		usersInsertArray.add( userInstance );

		//sql->addRow( userInstance );

	}


	sql->addRows( usersInsertArray );



	clock_t toc = clock();

	printf("Multiply: %f seconds, rows: %i\n", (double)( toc - tic ) / CLOCKS_PER_SEC, 10000);



	array * usersA 	= sql->fetchRows( "SELECT * FROM user" );

	//user * firstUser = new user();

	user * firstUser = usersA->get( 1 );

	//firstUser->id =10;

	firstUser->username		= "updated";

	firstUser->userlevel	= 1111;

	firstUser->hash			= "new hash";

	console->log( "??", firstUser, "Yeey console.log workswith , , " );


	sql->update( firstUser );

	printf("before log\n\n");


	

	array * users 	= sql->fetchRows( "SELECT * FROM user  " );

	int userCount	= users->total;
	

	printf("added rows: %i\n", userCount);

	console->createHorisontalLine();

	printf("\e[1m");

	printf("	");

	printf("%-20s", "id" );

	printf("%-30s", "username" );

	printf("%-20s", "userLevel" );

	printf("%-30s", "Hash");

	printf("\e[m");

	printf("\n");

	console->createHorisontalLine();

	printf("users: %i\n", userCount);

	for (int i = 0; i < userCount; ++i)
	{

		struct user * userInstance = users->get( i );

		userInstance->id;

		userInstance->username;

		printf("	");

		printf("%-20i", userInstance->id);

		printf("%-30s", userInstance->username);

		printf("%-20i", userInstance->userlevel);

		printf("%-30s", userInstance->hash);

		printf( "\n" );//%-30s

	}

	sql->free();

	console->createHorisontalLine();

	

}

void abort() {


}


trying to connect.. :memory: Multiply: 0.000370 seconds, rows: 10000 ?? user : { username : updated id : 1 userlevel : 1111 hash : new hash addresses : this has to be fixed, array is not created. } Yeey console.log workswith , , before log added rows: 10 -------------------------------------------------------------------------------- id username userLevel Hash -------------------------------------------------------------------------------- users: 10 0 piet 3 12345 1 updated 1111 new hash 2 siebe 3 12345 3 gerben 3 12345 4 twain 3 12345 5 piet 3 12345 6 gurbe 3 12345 7 siebe 3 12345 8 gerben 3 12345 9 twain 3 12345 --------------------------------------------------------------------------------