forked from schacon/perl
-
Notifications
You must be signed in to change notification settings - Fork 1
/
smop-s0native-idconst.c
154 lines (115 loc) · 4.43 KB
/
smop-s0native-idconst.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/* Here is the implementation of the idconst type, which is used to
* create the pool of constant identifiers that are needed to
* bootstrap smop.
*/
#include "smop-base.h"
#include "smop-s0native.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>
/*#include <pthread.h>*/
#include <stdio.h>
static SMOP__Object** constlist;
static int constlist_size;
/*static pthread_rwlock_t constlist_lock;*/
/* The constant identifiers are not subject to garbage collection,
* they are used as-is all the time. In fact, the string is saved on
* them just to enable the stringification in the high-level.
*/
static SMOP__ResponderInterface* SMOP__NATIVE__idconst_RI;
typedef struct SMOP__NATIVE__idconst_struct {
SMOP__Object__BASE
int size;
char* content;
} SMOP__NATIVE__idconst_struct;
static int cmp_idconst(const void* p1, const void* p2) {
if (!p1 && !p2) {
return 0;
} else if (p1 && !p2) {
return 1;
} else if (!p1 && p2) {
return -1;
} else {
SMOP__NATIVE__idconst_struct* o1 = *(SMOP__NATIVE__idconst_struct**)p1;
SMOP__NATIVE__idconst_struct* o2 = *(SMOP__NATIVE__idconst_struct**)p2;
if (o1->size > o2->size) {
int r = strncmp(o1->content, o2->content, o2->size);
return r ? r : -1;
} else if (o2->size > o1->size) {
int r = strncmp(o1->content, o2->content, o1->size);
return r ? r : 1;
} else {
return strncmp(o1->content, o2->content, o1->size);
}
}
}
char* SMOP__NATIVE__idconst_fetch(SMOP__Object* value, int* retsize) {
assert(value->RI == SMOP__NATIVE__idconst_RI);
*retsize = ((SMOP__NATIVE__idconst_struct*)value)->size;
return ((SMOP__NATIVE__idconst_struct*)value)->content;
}
char* SMOP__NATIVE__idconst_fetch_with_null(SMOP__Object* value,int* retsize) {
char* str = SMOP__NATIVE__idconst_fetch(value,retsize);
char* str_with_null = malloc(sizeof(char) * (*retsize+1));
strncpy(str_with_null,str,*retsize);
str_with_null[*retsize] = '\0';
return str_with_null;
}
void SMOP__NATIVE__idconst_free(SMOP__Object* value) {
free(((SMOP__NATIVE__idconst_struct*)value)->content);
free(value);
}
static SMOP__Object* SMOP__NATIVE__idconst_createn_nolist(const char* value, int size) {
SMOP__NATIVE__idconst_struct* ret = (SMOP__NATIVE__idconst_struct*) malloc(sizeof(SMOP__NATIVE__idconst_struct));
ret->RI = SMOP__NATIVE__idconst_RI;
ret->size = size;
ret->content = malloc(sizeof(char) * size);
strncpy(ret->content, value, size);
return (SMOP__Object*) ret;
}
SMOP__Object* SMOP__NATIVE__idconst_create(const char* value) {
return SMOP__NATIVE__idconst_createn(value,strlen(value));
}
SMOP__Object* SMOP__NATIVE__idconst_createn(const char* value, int size) {
SMOP__Object* candidate = SMOP__NATIVE__idconst_createn_nolist(value,size);
/* assert(pthread_rwlock_rdlock(&constlist_lock) == 0);*/
SMOP__Object** ret = bsearch(&candidate, constlist, constlist_size, sizeof(SMOP__Object*), cmp_idconst);
/* assert(pthread_rwlock_unlock(&constlist_lock) == 0);*/
if (ret) {
SMOP__NATIVE__idconst_free(candidate);
return *ret;
} else {
/* assert(pthread_rwlock_wrlock(&constlist_lock) == 0);*/
constlist_size++;
constlist = realloc(constlist, constlist_size * sizeof(SMOP__Object*));
assert(constlist);
constlist[constlist_size - 1] = candidate;
qsort(constlist, constlist_size, sizeof(SMOP__Object*), cmp_idconst);
/* assert(pthread_rwlock_unlock(&constlist_lock) == 0);*/
return candidate;
}
}
void smop_idconst_init() {
/* create the responder interface */
SMOP__NATIVE__idconst_RI = calloc(1,sizeof(SMOP__ResponderInterface));
assert(SMOP__NATIVE__idconst_RI);
SMOP__NATIVE__idconst_RI->MESSAGE = smop_placeholder_message;
SMOP__NATIVE__idconst_RI->REFERENCE = smop_noop_reference;
SMOP__NATIVE__idconst_RI->RELEASE = smop_noop_release;
SMOP__NATIVE__idconst_RI->WEAKREF = smop_noop_weakref;
SMOP__NATIVE__idconst_RI->id = "Constant Identifier";
SMOP__NATIVE__idconst_RI->RI = (SMOP__ResponderInterface *)SMOP__metaRI;
qsort(constlist, constlist_size, sizeof(SMOP__Object*), cmp_idconst);
/* assert(pthread_rwlock_init(&constlist_lock, NULL) == 0);*/
}
void smop_idconst_destr() {
int i;
for (i = constlist_size - 1; i >= 0; i--) {
SMOP__NATIVE__idconst_free(constlist[i]);
constlist[i] = NULL;
}
/* destroy the responder interface. */
free(SMOP__NATIVE__idconst_RI);
free(constlist); constlist_size = 0;
/* pthread_rwlock_destroy(&constlist_lock);*/
}