Skip to content

Commit

Permalink
(new) Implementing Magazine and Unique.
Browse files Browse the repository at this point in the history
Primarily of interest:
- `Magazine->of()`, depending on
- `_magazine__hash()` and
- `Unique->of()`
  • Loading branch information
ELLIOTTCABLE committed Jun 7, 2011
1 parent 157547b commit cf4736b
Show file tree
Hide file tree
Showing 4 changed files with 171 additions and 40 deletions.
4 changes: 2 additions & 2 deletions Source/Core.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@


/* Yes, I’m a pedant. Get over it. */
typedef void * e(pointer);

typedef void * e(pointer);
typedef unsigned char e(byte);

# if !defined(__has_attribute)
# define has_no_has_attribute
Expand Down
2 changes: 1 addition & 1 deletion Source/Types/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ typedef struct e(typeRepresentation) * e(typeRepresentation);

struct e(typeRepresentation) {
e(pointer) family;
char name[64]; };
byte name[64]; };

This comment has been minimized.

Copy link
@judofyr

judofyr Jun 7, 2011

Shouldn't this be e(byte)?

This comment has been minimized.

Copy link
@ELLIOTTCABLE

ELLIOTTCABLE Jun 7, 2011

Author Owner

Nice catch! Pull request? :3

Click “View file @ cf4736b” above, then click the “edit” link at the top; it will fork the project and open the file for editing, and then automatically create a pullrequest with the changes you make.


struct e(thing) {
e(pointer) const pointer;
Expand Down
98 changes: 75 additions & 23 deletions Source/Types/label/Magazine.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,28 +17,42 @@
typedef struct e(unique) * e(unique);
typedef struct e(magazine) * e(magazine);

struct e(unique) { void* nothing; };
struct e(magazine) { void* nothing; };
typedef unsigned int e(unique_size);
typedef unsigned int e(magazine_length);

struct e(unique) {
e(pointer) content;
e(unique_size) bytes;
e(unique) overflow; };
struct e(magazine) {
e(unique) * uniques;
e(byte) bits; };


struct E(Unique) {
// Functions ==============
/// `Unique` family functions
e(unique) (*create)(void);
struct e(unique) * (*allocate)(void);
e(unique) (*initialize) ( struct e(unique)* this);
e(unique) (*create) ( e(pointer) content, e(unique_size) bytes );
struct e(unique) * (*allocate)(void);
e(unique) (*initialize) ( struct e(unique)* this, e(pointer) content, e(unique_size) bytes );

/// `struct unique` instance functions
e(unique) (*of) ( e(unique) this, e(pointer) content, e(unique_size) bytes );
void (*affix) ( e(unique) this, e(unique) sibling );
} IF_INTERNALIZED(extern *Unique);

struct E(Magazine) {
// Functions ==============
/// `Magazine` family functions
e(magazine) (*create)(void);
struct e(magazine) * (*allocate)(void);
e(magazine) (*initialize) ( struct e(magazine)* this );
//
//
// NOTE: `->initialize()` truncates its `extent` argument to the closest power of two below the given integer.
e(magazine) (*create) ( e(magazine_length) extent );
struct e(magazine) * (*allocate)(void);
e(magazine) (*initialize) ( struct e(magazine)* this, e(magazine_length) extent );

/// `struct magazine` instance functions
e(unique) (*of) ( e(magazine) this, e(pointer) content, e(unique_size) bytes );
} IF_INTERNALIZED(extern *Magazine);

extern void MAKE_EXTERNAL(register_Unique)(void);
Expand All @@ -53,12 +67,18 @@ extern void MAKE_EXTERNAL(register_Magazine)(void);
# define DECLARATIONS
# include <stdlib.h>
# include <string.h>
# include <math.h>
# undef DECLARATIONS

static const magazine_length offset_basis = 2166136261;
static const magazine_length FNV_prime = (1 << 24) + (1 << 8) + 0x93;


static unique Unique__create ( pointer content, unique_size bytes);
static struct unique * Unique__allocate(void);
static unique Unique__initialize (struct unique* this, pointer content, unique_size bytes);

static unique Unique__create(void);
static struct unique * Unique__allocate(void);
static unique Unique__initialize (struct unique* this);
static unique unique__of (unique this, pointer content, unique_size bytes);


IF_EXTERNALIZED(static) struct Unique * // »
Expand All @@ -69,49 +89,81 @@ void Paws__register_Unique(void) { Unique = malloc(sizeof( struct Unique ));
data = {
.create = Unique__create,
.allocate = Unique__allocate,
.initialize = Unique__initialize };
.initialize = Unique__initialize,

.of = unique__of };

memcpy(Unique, &data, sizeof( struct Unique )); }


static magazine Magazine__create(void);
static magazine Magazine__create (magazine_length extent);
static struct magazine * Magazine__allocate(void);
static magazine Magazine__initialize (struct magazine* this);
static magazine Magazine__initialize (struct magazine* this, magazine_length extent);

static unique magazine__of (magazine this, pointer content, unique_size bytes);
static magazine_length _magazine__hash (magazine this, pointer content, unique_size bytes);

IF_EXTERNALIZED(static) struct Magazine * // »
Magazine = NULL;
void Paws__register_Magazine(void) { Magazine = malloc(sizeof( struct Magazine ));

auto struct Magazine // »
data = {
.create = Magazine__create,
.allocate = Magazine__allocate,
.initialize = Magazine__initialize };
.create = Magazine__create,
.allocate = Magazine__allocate,
.initialize = Magazine__initialize,

.of = magazine__of };

memcpy(Magazine, &data, sizeof( struct Magazine )); }


unique Unique__create(void) {
return Unique->initialize(Unique->allocate()); }
unique Unique__create(pointer content, unique_size bytes) {
return Unique->initialize(Unique->allocate(), content, bytes); }

struct unique * Unique__allocate(void) {
return malloc(sizeof( struct unique )); }

unique Unique__initialize(struct unique* this) {
unique Unique__initialize(struct unique* this, pointer content, unique_size bytes) {

this->content = content;
this->bytes = bytes;

return this; }

unique unique__of(unique this, pointer content, unique_size bytes) {
if (this->bytes == bytes && memcmp(this->content, content, bytes) == 0)
return this;
else if (this->overflow == NULL)
return Unique->create(content, bytes); else
return unique__of(this->overflow, content, bytes); }

magazine Magazine__create(void) {
return Magazine->initialize(Magazine->allocate()); }
magazine Magazine__create(magazine_length extent) {
return Magazine->initialize(Magazine->allocate(), extent); }

struct magazine * Magazine__allocate(void) {
return malloc(sizeof( struct magazine )); }

magazine Magazine__initialize(struct magazine* this) {
magazine Magazine__initialize(struct magazine* this, magazine_length extent) {

this->bits = (byte)log2(extent);
this->uniques = malloc((1 << this->bits) * sizeof( struct unique* ));

return this; }

unique magazine__of(magazine this, pointer content, unique_size bytes) { unique it; magazine_length // »
hash = _magazine__hash( this, content, bytes);

if ( (it = this->uniques[hash]) != NULL )
return Unique->of(it, content, bytes); else
return this->uniques[hash] = Unique->create(content, bytes); }

static // »
magazine_length _magazine__hash(magazine this, pointer content, unique_size bytes) { bytes--; magazine_length // »
hash = offset_basis;

while (bytes--) { hash = (hash ^ ((byte*)content)[bytes]) * FNV_prime; }
return ((hash >> this->bits) ^ hash) & (((magazine_length)1 << this->bits) - 1); }


# endif //!defined(MAGAZINE_IMPLEMENTATION) && !defined(DECLARATIONS)
107 changes: 93 additions & 14 deletions Source/Types/label/Magazine.tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,60 @@

# define DECLARATIONS
# include "Cest.c/Source/Cest.c"
# include <stdio.h>
# undef DECLARATIONS


CEST(Unique, allocate) { auto struct unique * // »
a_unique_pointer = Unique->allocate();

// This is an absolutely paltry test, but I don’t know what else I can do here. /=
ASSERT_NOT_NULL( a_unique_pointer );

SUCCEED; }}

CEST(Unique, initialize) { auto struct unique * // »
a_unique_pointer = Unique->allocate();

Unique->initialize(a_unique_pointer, "foo", 4);
ASSERT_STREQUAL( (*a_unique_pointer).content, "foo" );
ASSERT_EQUAL ( (*a_unique_pointer).bytes, 4 );

SUCCEED; }}

CEST(Unique, of) { auto unique result, unique4, unique5;
auto unique unique1 = Unique->create("widget", 7);
auto unique unique2 = Unique->create("qux", 4); unique1->overflow = unique2;
auto unique unique3 = Unique->create("quux", 5); unique2->overflow = unique3;

// `this` matches
result = Unique->of(unique1, "widget", 7);
ASSERT_EQUAL( result, unique1 );

// Element in list matches
result = Unique->of(unique1, "quux", 5);
ASSERT_EQUAL( result, unique3 );

// No content match, but a length match
unique4 = Unique->of(unique1, "foobar", 7);
ASSERT_NOT_EQUAL( unique4, unique1 );
ASSERT_NOT_EQUAL( unique4, unique2 );
ASSERT_NOT_EQUAL( unique4, unique3 );
ASSERT_STREQUAL ( unique4->content, "foobar" );
ASSERT_EQUAL ( unique4->bytes, 7 );

// No content match, no length match
unique5 = Unique->of(unique1, "abcde", 6);
ASSERT_NOT_EQUAL( unique5, unique1 );
ASSERT_NOT_EQUAL( unique5, unique2 );
ASSERT_NOT_EQUAL( unique5, unique3 );
ASSERT_NOT_EQUAL( unique5, unique4 );
ASSERT_STREQUAL ( unique5->content, "abcde" );
ASSERT_EQUAL ( unique5->bytes, 6 );

SUCCEED; }}


CEST(Magazine, allocate) { auto struct magazine * // »
a_magazine_pointer = Magazine->allocate();

Expand All @@ -16,27 +67,55 @@ CEST(Magazine, allocate) { auto struct magazine * // »
CEST(Magazine, initialize) { auto struct magazine * // »
a_magazine_pointer = Magazine->allocate();

Magazine->initialize(a_magazine_pointer);
//ASSERT_NULL( (*a_magazine_pointer).first );
//ASSERT_NULL( (*a_magazine_pointer).last );
//ASSERT_ZERO( (*a_magazine_pointer).length );
Magazine->initialize(a_magazine_pointer, 16);
ASSERT_NOT_NULL( (*a_magazine_pointer).uniques );
ASSERT_EQUAL ( (*a_magazine_pointer).bits, 4 );

SUCCEED; }}


CEST(Unique, allocate) { auto struct unique * // »
a_unique_pointer = Unique->allocate();
CEST(Magazine, of) { auto unique unique1, unique2, unique3, result1, result2, result3; auto magazine // »
the_magazine = Magazine->create(64);

// This is an absolutely paltry test, but I don’t know what else I can do here. /=
ASSERT_NOT_NULL( a_unique_pointer );
unique1 = Magazine->of(the_magazine, "foo", 4);
ASSERT_NOT_NULL ( unique1 );
ASSERT_STREQUAL ( unique1->content, "foo" );
ASSERT_EQUAL ( unique1->bytes, 4 );

unique2 = Magazine->of(the_magazine, "bar", 4);
ASSERT_NOT_NULL ( unique2 );
ASSERT_STREQUAL ( unique2->content, "bar" );
ASSERT_EQUAL ( unique2->bytes, 4 );

unique3 = Magazine->of(the_magazine, "widget", 7);
ASSERT_NOT_NULL ( unique3 );
ASSERT_STREQUAL ( unique3->content, "widget" );
ASSERT_EQUAL ( unique3->bytes, 7 );

result1 = Magazine->of(the_magazine, "foo", 4);
ASSERT_EQUAL( unique1, result1 );

result2 = Magazine->of(the_magazine, "bar", 4);
ASSERT_EQUAL( unique2, result2 );

result3 = Magazine->of(the_magazine, "widget", 7);
ASSERT_EQUAL( unique3, result3 );

// TODO: Add `SANITY()` checks for, well, everything.
SUCCEED; }}

CEST(Unique, initialize) { auto struct unique * // »
a_unique_pointer = Unique->allocate();
CEST(Magazine, _hash) { auto magazine_length a_hash;

a_hash = _magazine__hash(Magazine->create(1<<3), "foobar", 7);
ASSERT( a_hash <= 1 << 3);
//printf("2³: 0x%X, ", a_hash);

a_hash = _magazine__hash(Magazine->create(1<<9), "foobar", 7);
ASSERT( a_hash <= 1 << 9);
//printf("2⁹: 0x%X, ", a_hash);

Unique->initialize(a_unique_pointer);
//ASSERT_NULL( (*a_unique_pointer).next );
//ASSERT_NULL( (*a_unique_pointer).previous );
a_hash = _magazine__hash(Magazine->create(1<<15), "foobar", 7);
ASSERT( a_hash <= 1 << 15);
//printf("2¹⁵: 0x%X", a_hash);

// TODO: Add `SANITY()` checks for hash equality and zero-ness.
SUCCEED; }}

0 comments on commit cf4736b

Please sign in to comment.