Skip to content

Instantly share code, notes, and snippets.

@eatnumber1
Created September 30, 2010 22:43
Show Gist options
  • Save eatnumber1/605457 to your computer and use it in GitHub Desktop.
Save eatnumber1/605457 to your computer and use it in GitHub Desktop.
Object-Oriented C
Your compiler must support blocks.
To compile, run ONE of the following:
gcc -o ooc -std=c99 -fblocks ooc.c
clang -o ooc ooc.c
The output looks like this:
Integer: 1337
String: "Hello World!"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stddef.h>
#include <stdbool.h>
#include <Block.h>
typedef struct {
char *_typeName;
void (^_setTypeName)( const char * );
const char *(^getTypeName)();
char *(^toString)();
void (^delete)();
} Object;
typedef struct {
Object super;
int _value;
int (^getValue)();
} Integer;
typedef struct {
Object super;
char *_value;
const char *(^getValue)();
void (^setValue)( const char * );
} String;
#define CONSTRUCTOR_NAME( type ) new$OBJECT$ ##type
#define INITIALIZER_NAME( type ) init$OBJECT$ ##type
#define new( type, args... ) CONSTRUCTOR_NAME(type)(args)
#define _init( type, args... ) INITIALIZER_NAME(type)(args)
static void INITIALIZER_NAME(Object)( Object *t ) {
__block Object *this = t;
this->_setTypeName = Block_copy(^ ( const char *typeName ) {
if( this->_typeName != NULL ) free(this->_typeName);
this->_typeName = strdup(typeName);
});
this->getTypeName = Block_copy(^ const char * {
return this->_typeName;
});
this->_typeName = NULL;
this->toString = NULL;
this->delete = Block_copy(^ {
Block_release(this->_setTypeName);
Block_release(this->getTypeName);
free(this->_typeName);
});
this->_setTypeName("Object");
}
static void INITIALIZER_NAME(Integer)( Integer *t, int value ) {
__block Integer *this = t;
_init(Object, &this->super);
this->super._setTypeName("Integer");
this->getValue = Block_copy(^ int () {
return this->_value;
});
this->_value = value;
this->super.toString = Block_copy(^ char * {
char *ret;
asprintf(&ret, "%s: %d", this->super.getTypeName(), this->getValue());
return ret;
});
__block void (^Object_delete)() = this->super.delete;
this->super.delete = Block_copy(^ {
Block_release(this->super.toString);
Object_delete();
Block_release(Object_delete);
Block_release(this->getValue);
});
}
static void INITIALIZER_NAME(String)( String *t, const char *value ) {
__block String *this = t;
_init(Object, &this->super);
this->super._setTypeName("String");
this->getValue = Block_copy(^ const char * {
return this->_value;
});
this->setValue = Block_copy(^ ( const char *value ) {
if( this->_value != NULL ) free(this->_value);
this->_value = strdup(value);
});
this->super.toString = Block_copy(^ char * {
char *ret;
asprintf(&ret, "%s: \"%s\"", this->super.getTypeName(), this->getValue());
return ret;
});
__block void (^Object_delete)() = this->super.delete;
this->super.delete = Block_copy(^ {
Block_release(this->super.toString);
Object_delete();
Block_release(Object_delete);
Block_release(this->setValue);
Block_release(this->getValue);
free(this->_value);
});
this->_value = NULL;
this->setValue(value);
}
static String *CONSTRUCTOR_NAME(String)( const char *value ) {
String *this = malloc(sizeof(String));
_init(String, this, value);
return this;
}
static Integer *CONSTRUCTOR_NAME(Integer)( int value ) {
Integer *this = malloc(sizeof(Integer));
_init(Integer, this, value);
return this;
}
static void delete( void *t ) {
Object *this = (Object *) t;
void (^delete_block)() = this->delete;
delete_block();
Block_release(delete_block);
free(this);
}
int main() {
Object *objs[] = {
(Object *) new(Integer, 1337),
(Object *) new(String, "Hello World!"),
NULL
};
for( Object **o = objs; *o != NULL; o++ ) {
char *string = (*o)->toString();
printf("%s\n", string);
free(string);
delete(*o);
}
return EXIT_SUCCESS;
}
@saucetray
Copy link

this is 💯

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment