-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathnv_dict.c
207 lines (184 loc) · 5.93 KB
/
nv_dict.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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
#include "nv.h"
/*
このシステム上では、あらゆるオブジェクトがDictとみなせる。
Relationのrelをキーとし、与えられたキーと同値なrelをもつRelationの
先にあるオブジェクトを返す。
同値とは、プリミティブなノードであれば、そのノードの値が一致すること。
複雑なノードに関しては、現状では定義しない。(None != Noneが常に成立)
該当するノードが複数ある場合、
複数返すことが前提になっている関数は、可能な限り全てを返し、
ひとつしか返せない関数は、そのうちのどれかを返す。
どのNodeひとつを返すかは実装依存である。
*/
NV_ID NV_Dict_addKey
(const NV_ID *root, const NV_ID *key, const NV_ID *value)
{
return NV_NodeID_createRelation(root, key, value);
}
NV_ID NV_Dict_addKeyByCStr
(const NV_ID *root, const char *key, const NV_ID *value)
{
NV_ID strid = NV_Node_createWithString(key);
return NV_Dict_addKey(root, &strid, value);
}
NV_ID NV_Dict_addUniqueIDKey
(const NV_ID *root, const NV_ID *key, const NV_ID *value)
{
return NV_NodeID_createUniqueIDRelation(root, key, value);
}
NV_ID NV_Dict_addUniqueEqKeyByCStr
(const NV_ID *root, const char *key, const NV_ID *value)
{
NV_ID strid = NV_Node_createWithString(key);
return NV_NodeID_createUniqueEqRelation(root, &strid, value);
}
NV_ID NV_Dict_removeUniqueIDKey(const NV_ID *root, const NV_ID *key)
{
// removeと言っているが、実際はリンク先をNOT_FOUNDに向けるだけ
return NV_NodeID_createUniqueIDRelation(root, key, &NODEID_NOT_FOUND);
}
NV_ID NV_Dict_removeUniqueEqKeyByCStr(const NV_ID *root, const char *key)
{
// removeと言っているが、実際はリンク先をNOT_FOUNDに向けるだけ
NV_ID strid = NV_Node_createWithString(key);
return NV_NodeID_createUniqueEqRelation(root, &strid, &NODEID_NOT_FOUND);
}
NV_ID NV_Dict_get(const NV_ID *root, const NV_ID *key)
{
// keyが同じ値を持つ(IDが等しいとは限らない)オブジェクトを返す。
return NV_NodeID_getEqRelatedNodeFrom(root, key);
}
NV_ID NV_Dict_getEqID(const NV_ID *root, const NV_ID *key)
{
return NV_NodeID_getRelatedNodeFrom(root, key);
}
int NV_Dict_Internal_merge(void *d, const NV_ID *reln, const NV_ID *rel, const NV_ID *to)
{
PARAM_UNUSED(reln);
NV_Dict_addUniqueIDKey((const NV_ID *)d, rel, to);
return 1;
}
NV_ID NV_Dict_createMergedNode(const NV_ID *a, const NV_ID *b)
{
NV_ID m = NV_Node_create();
NV_Dict_foreach(a, &m, NV_Dict_Internal_merge);
NV_Dict_foreach(b, &m, NV_Dict_Internal_merge);
return m;
}
/*
NV_ID NV_Dict_getAll(const NV_ID *root, const NV_ID *key)
{
// VARY SLOW!!!!!
// keyが同じ値を持つ(IDが等しいとは限らない)オブジェクトを
// すべて含むリストを返す。
const NV_Node *n;
const NV_Relation *reld;
NV_ID list;
//
list = NV_Array_create();
//
for(n = nodeRoot.next; n; n = n->next){
if(n->type == kRelation){
reld = n->data;
if( NV_NodeID_isEqual(&reld->from, root) &&
NV_NodeID_isEqualInValue(&reld->rel, key)){
NV_Array_push(&list, &reld->to);
}
}
}
return list;
}
*/
int NV_Dict_foreach
(const NV_ID *dict, void *d, int (*f)(void *d, const NV_ID *reln, const NV_ID *rel, const NV_ID *to))
{
// ノードdictを起点とするすべての関係をたどって。そのrelationとtoをfに引き渡す。
// fの戻り値がfalseの場合はそこでループを中止する。
// 戻り値は、fを呼んだ回数である。
const NV_Node *n;
const NV_Relation *reld;
int count = 0;
for(n = NV_Node_getNextNode(&nodeRoot); n; n = NV_Node_getNextNode(n)){
reld = NV_Node_getDataAsType(n, kRelation);
if(reld && NV_NodeID_isEqual(&reld->from, dict)){
count++;
NV_ID id = NV_Node_getID(n);
if(!f(d, &id, &reld->rel, &reld->to)) break;
}
}
return count;
}
int NV_Dict_foreachWithRelFilter
(const NV_ID *dict, void *d, int (*f)(void *d, const NV_ID *reln, const NV_ID *rel, const NV_ID *to), int (*filter)(const NV_ID *rel))
{
// ノードdictを起点とするすべての関係をたどって。そのrelationとtoをfに引き渡す。
// filterがtrueを返す関係のノードのみたどる。
// fの戻り値がfalseの場合はそこでループを中止する。
// 戻り値は、fを呼んだ回数である。
const NV_Node *n;
const NV_Relation *reld;
int count = 0;
NV_ID id;
for(n = NV_Node_getNextNode(&nodeRoot); n; n = NV_Node_getNextNode(n)){
reld = NV_Node_getDataAsType(n, kRelation);
id = NV_Node_getID(n);
if(reld && NV_NodeID_isEqual(&reld->from, dict) && filter(&id)){
count++;
NV_ID id = NV_Node_getID(n);
if(!f(d, &id, &reld->rel, &reld->to)) break;
}
}
return count;
}
NV_ID NV_Dict_getByStringKey
(const NV_ID *root, const char *key)
{
NV_ID strid = NV_Node_createWithString(key);
return NV_Dict_get(root, &strid);
}
int NV_Dict_Internal_printSub(void *d, const NV_ID *reln, const NV_ID *rel, const NV_ID *to)
{
PARAM_UNUSED(reln);
printf("├─── ");
NV_Node_printPrimVal(rel);
printf(": ");
NV_Node_printPrimVal(to);
printf("\n");
(*(int *)d)++;
return 1;
}
void NV_Dict_print(const NV_ID *root)
{
int cnt = 0;
NV_Node_printPrimVal(root);
printf(":\n");
NV_Dict_foreach(root, &cnt, NV_Dict_Internal_printSub);
printf("(%d items)\n", cnt);
}
typedef struct {
int depth;
int current;
} NV_Dict_DepthInfo;
int NV_Dict_Internal_printWithDepthSub(void *d, const NV_ID *reln, const NV_ID *rel, const NV_ID *to)
{
PARAM_UNUSED(reln);
NV_Dict_DepthInfo *info = d;
int i;
for(i = 0; i < info->current; i++){
printf("│ ");
}
printf("├── ");
NV_Node_printPrimVal(rel);
printf(": ");
NV_Dict_printWithDepth(to, info->depth, info->current + 1);
return 1;
}
void NV_Dict_printWithDepth(const NV_ID *root, int depth, int current)
{
NV_Node_printPrimVal(root); printf("\n");
if(depth <= current) return;
NV_Dict_DepthInfo info;
info.depth = depth;
info.current = current;
NV_Dict_foreach(root, &info, NV_Dict_Internal_printWithDepthSub);
}