|
|
1.1 root 1: /*************************************************************/
2: /** **/
3: /** Microsoft RPC Examples **/
4: /** Dictionary Application **/
1.1.1.2 root 5: /** Copyright(c) Microsoft Corp. 1992 **/
1.1 root 6: /** **/
7: /*************************************************************/
8:
9: /*************************************************************************/
10: /*** ***/
1.1.1.3 ! root 11: /*** Example dictionary using splay trees: ***/
1.1 root 12: /*** ***/
13: /*************************************************************************/
14:
15: #include <stdlib.h>
1.1.1.3 ! root 16: #include <stdio.h>
1.1 root 17: #include <string.h>
18:
1.1.1.3 ! root 19: #include "replay.h" // header file generated by MIDL compiler
1.1 root 20: #include "dict0.h"
21: #include "util0.h"
22:
23: #define TAB_STOPS 3
24:
25: /*************************************************************************/
26: /*** Declarations (from replay.h) ***/
27: /*************************************************************************/
28:
29: /*
30: typedef struct _Record {
31: short key; // RPC "generation"
32: [string] char* name; // contributor
33: } Record;
34:
35: typedef struct _RecordTreeNode RecordTreeNode;
36:
37: typedef struct _RecordTreeNode {
38: RecordTreeNode *left; // left child pointer
39: RecordTreeNode *right; // right child pointer
40: Record *item; // pointer to a Record structure
41: } RecordTreeNode;
42:
43: typedef struct _RDict {
44: RecordTreeNode *root; // pointer to the root of a SAT
45: long size; // number of records in dictionary
46: } RDict;
47:
48: // RDict is used for marshalling a complete dictionary.
49:
50: typedef enum {
51: DICT_SUCCESS,
52: DICT_ITEM_ALREADY_PRESENT,
53: DICT_ITEM_NOT_FOUND,
54: DICT_FIRST_ITEM,
55: DICT_LAST_ITEM,
56: DICT_EMPTY_DICTIONARY,
57: DICT_NULL_ITEM
1.1.1.3 ! root 58: } VDict_Status;
1.1 root 59:
60: typedef struct _DictState {
61: short ref_count; // for shared dictionaries
62: Record * curr_record; // for global iterators
63: } DictState;
64: */
65:
66: /*************************************************************************/
67: /*** Internal state access methods ***/
68: /*************************************************************************/
69:
70: #define RDICT_CURR_RECORD(dict) (((DictState*)dict->state)->curr_record)
71:
1.1.1.3 ! root 72: #define RDICT_REF_COUNT(dict) (((DictState*)dict->state)->ref_count)
1.1 root 73:
1.1.1.3 ! root 74: #define RDICT_STATE(dict) (((RDict*)dict)->state)
1.1 root 75:
76: static int active_dictionary = 0;
77:
78: /*************************************************************************/
79: /*** Generic Dictionary Operations: (From dict0.h) ***/
80: /*** ***/
81: /*** Dictionary *Dict_New(Cmp_rec*, Splay*, print_rec*) ***/
82: /*** ***/
83: /*** Dict_Status Dict_Find(Dictionary*, Item*) ***/
84: /*** Dict_Status Dict_Next(Dictionary*, Item*) ***/
85: /*** Dict_Status Dict_Prev(Dictionary*, Item*) ***/
86: /*** Dict_Status Dict_Insert(Dictionary*, Item*) ***/
87: /*** Dict_Status Dict_Delete(Dictionary*, Item**) ***/
88: /*** ***/
89: /*** Item* DICT_CURR_ITEM(Dict*) ***/
90: /*************************************************************************/
91:
92: /*************************************************************************/
93: /*** Virtual Dictionary Operations: (From replay.h) ***/
94: /*** ***/
95: /*** VDict_Status VDict_New(OUT VDict **) ***/
96: /*** ***/
97: /*** VDict_Status VDict_Find(IN VDict*, IN OUT Record**) ***/
98: /*** VDict_Status VDict_Next(IN VDict*, IN OUT Record**) ***/
99: /*** VDict_Status VDict_Prev(IN VDict*, IN OUT Record**) ***/
100: /*** VDict_Status VDict_Insert(IN VDict*, IN Record*) ***/
101: /*** VDict_Status VDict_Delete(IN VDict*, IN OUT Record**) ***/
102: /*** ***/
103: /*** VDict_Status VDict_Curr_Item(IN VDict*, OUT Record**); ***/
104: /*** VDict_Status VDict_Curr_Delete(IN VDict*, OUT Record**); ***/
105: /*** VDict_Status VDict_Curr_Next(IN VDict*, OUT Record**); ***/
106: /*** VDict_Status VDict_Curr_Prev(IN VDict*, OUT Record**); ***/
107: /*** ***/
108: /*** VDict_Status VDict_Get_Dict(IN VDict*, OUT RDict**) ***/
109: /*************************************************************************/
110:
111: /*************************************************************************/
112: /*** context rundown routine ***/
113: /*************************************************************************/
114:
1.1.1.3 ! root 115: void __RPC_USER VDict_rundown (VDict v_dict)
1.1 root 116: {
117: Dictionary * pdict = (Dictionary*) v_dict;
118: short count = --RDICT_REF_COUNT(pdict);
119:
120: printf("# of remaining users of context: %d\n\n",
1.1.1.3 ! root 121: RDICT_REF_COUNT(pdict) );
1.1 root 122:
1.1.1.3 ! root 123: if (RDICT_REF_COUNT(pdict) <= 0) {
1.1 root 124: printf("CLOSING CONTEXT\n\n");
125:
126: // free the splay tree
127: RDict_Free_Dict(v_dict);
128:
129: // free the dictionary object
1.1.1.3 ! root 130: free_state((DictState*) pdict->state);
! 131: MIDL_user_free(v_dict);
! 132: if (count == 0)
1.1 root 133: active_dictionary = 0;
134: }
135: }
136:
137: // For now: need to allocate a new item record prior to operation,
138: // for all OUT and IN OUT arguments, as the callee stub will free
139: // storage allocated for such pointer parameters.
140: //
141: // Will be fixed by the introduction of [allocate(dont_free)]
142: // ACF pointer type and parameter attribute.
143:
144: /**************************************************************************
145: * VDict_New initializes a new dictionary if (1) a non shared dictionary
146: * was requested, or (2) a shared dictionary was requested, but no shared
147: * dictionary is currently active. There is at most one shared dictionary
148: * at any point in time.
149: *
150: * BUGBUG: shared dictionaries are *NOT* locked (by semaphore, to
151: * serialize access to them. They *should be, though...
152: **************************************************************************
153: */
154:
155: VDict_Status
156: VDict_New(
157: IN short shared_dict,
158: OUT VDict * v_dict
159: )
160: {
161: Dictionary * pdict0;
162: static Dictionary * pdict;
163:
164: if (!active_dictionary || !shared_dict) {
1.1.1.3 ! root 165: // server side dictionary initialization
1.1 root 166: pdict0 = Dict_New(comp, tdSplay, printRecord);
167:
1.1.1.3 ! root 168: // Initializes RDICT_CURR_RECORD(pdict0) to
! 169: // "minus infinity" in the order
1.1 root 170: ((RDict*)pdict0)->state = allocate_state();
171:
172: Init_dict(pdict0);
173: *v_dict = (VDict)pdict0;
174:
175: if (shared_dict) {
176: printf("OPENING SHARED DICTIONARY CONTEXT!\n\n");
177: active_dictionary = 1;
178: pdict = pdict0;
179: RDICT_REF_COUNT(pdict)++;
180: } // else RDICT_REF_COUNT(pdict0) = 0;
181: }
182: else {
183: RDICT_REF_COUNT(pdict)++;
184: printf("# of users of shared context: %d\n\n", RDICT_REF_COUNT(pdict));
185: *v_dict = (VDict)pdict;
186: }
187:
188: return(DICT_SUCCESS);
189: }
190:
191: VDict_Status
192: VDict_Find(
193: IN VDict v_dict,
194: IN OUT Record ** item
195: )
196: {
197: Dictionary * pdict = (Dictionary*) (v_dict);
198: Dict_Status status;
199:
200: status = Dict_Find(pdict, *item);
201: if ( (pdict == NULL) || DICT_EMPTY(pdict) ) {
1.1.1.3 ! root 202: *item = NULL;
! 203: }
1.1 root 204: else {
205: *item = DICT_CURR_ITEM(pdict);
206: *item = ItemDuplicate(*item);
207: }
208: return( (VDict_Status)status );
209: }
210:
211: VDict_Status
212: VDict_Next(
213: IN VDict v_dict,
214: IN OUT Record ** item
215: )
216: // get successor of *item, and update *item to point to it
217: {
218: Dictionary * pdict = (Dictionary*) (v_dict);
219: Dict_Status status;
220:
221: status = Dict_Next(pdict, *item);
222: if ( (pdict == NULL) || DICT_EMPTY(pdict) ) {
1.1.1.3 ! root 223: *item = NULL;
! 224: }
1.1 root 225: else {
226: if (*item == NULL)
227: ItemCopy(DICT_CURR_ITEM(pdict), RDICT_CURR_RECORD(pdict));
228: *item = DICT_CURR_ITEM(pdict);
229: }
230: *item = ItemDuplicate(*item);
231: return( (VDict_Status)status );
232: }
233:
234: VDict_Status
235: VDict_Prev(
236: IN VDict v_dict,
237: IN OUT Record ** item
238: )
239: // get predecessor of *item, and update *item to point to it
240: {
241: Dictionary * pdict = (Dictionary*) (v_dict);
242: Dict_Status status;
243:
244: status = Dict_Prev(pdict, *item);
245: if ( (pdict == NULL) || DICT_EMPTY(pdict) ) {
1.1.1.3 ! root 246: *item = NULL;
! 247: }
1.1 root 248: else {
249: if (*item == NULL)
250: ItemCopy(DICT_CURR_ITEM(pdict), RDICT_CURR_RECORD(pdict));
251: *item = DICT_CURR_ITEM(pdict);
252: }
253: *item = ItemDuplicate(*item);
254: return( (VDict_Status)status );
255: }
256:
257: VDict_Status
258: VDict_Curr_Next(
259: IN VDict v_dict,
260: OUT Record ** item
261: )
262: // get successor of RDICT_CURR_RECORD(v_dict),
263: // and update *item to point to it (global iterator prev)
264: {
265: Dictionary * pdict = (Dictionary*) (v_dict);
266: Dict_Status status;
267:
268: if ( (pdict == NULL) || DICT_EMPTY(pdict) ) {
269: status = EMPTY_DICTIONARY;
1.1.1.3 ! root 270: *item = NULL;
! 271: }
1.1 root 272: else {
273: status = Dict_Next(pdict, RDICT_CURR_RECORD(pdict));
274: ItemCopy(DICT_CURR_ITEM(pdict), RDICT_CURR_RECORD(pdict));
275: *item = DICT_CURR_ITEM(pdict);
276: }
277: *item = ItemDuplicate(*item);
278: return( (VDict_Status)status );
279: }
280:
281: VDict_Status
282: VDict_Curr_Prev(
283: IN VDict v_dict,
284: OUT Record ** item
285: )
286: // get predecessor of RDICT_CURR_RECORD(v_dict),
287: // and update *item to point to it (global iterator prev)
288: {
289: Dictionary * pdict = (Dictionary*) (v_dict);
290: Dict_Status status;
291:
292: if ( (pdict == NULL) || DICT_EMPTY(pdict) ) {
293: status = EMPTY_DICTIONARY;
1.1.1.3 ! root 294: *item = NULL;
! 295: }
1.1 root 296: else {
297: // update RDICT_CURR_RECORD(pdict)
298: status = Dict_Prev(pdict, RDICT_CURR_RECORD(pdict));
299: ItemCopy(DICT_CURR_ITEM(pdict), RDICT_CURR_RECORD(pdict));
300: *item = DICT_CURR_ITEM(pdict);
301: }
302: *item = ItemDuplicate(*item);
303: return( (VDict_Status)status );
304: }
305:
306: VDict_Status
307: VDict_Insert(
308: IN VDict v_dict,
309: IN Record * item
310: )
311: {
312: Dictionary * pdict = (Dictionary*) (v_dict);
313: Dict_Status status;
314: Record * rp = makeRecord(item->key, item->name);
315:
316: status = Dict_Insert(pdict, rp); // No return value required.
317: return( (VDict_Status)status );
318: }
319:
320: VDict_Status
321: VDict_Delete(
322: IN VDict v_dict,
323: IN OUT Record ** item
324: )
325: {
326: Dictionary * pdict = (Dictionary*) (v_dict);
327: Dict_Status status;
328:
1.1.1.3 ! root 329: status = Dict_Delete(pdict, (void **)item);
! 330: // (*item) is returned by Dict_Delete!
1.1 root 331: return( (VDict_Status)status );
332: }
333:
334: VDict_Status
335: VDict_Curr_Item(
336: IN VDict v_dict,
337: OUT Record ** item
338: )
339: {
340: Dictionary * pdict = (Dictionary*) (v_dict);
341: Dict_Status status;
342:
343: if ( (pdict == NULL) || DICT_EMPTY(pdict) ) {
344: status = EMPTY_DICTIONARY;
1.1.1.3 ! root 345: *item = NULL;
! 346: }
1.1 root 347: else {
348: status = SUCCESS;
349: *item = DICT_CURR_ITEM(pdict);
350: }
351: *item = ItemDuplicate(*item);
352: return( (VDict_Status)status );
353: }
354:
355: VDict_Status
356: VDict_Curr_Delete(
357: IN VDict v_dict,
358: OUT Record ** item
359: )
360: {
361: Dictionary * pdict = (Dictionary*) (v_dict);
362: Dict_Status status;
363:
364: if ( (pdict == NULL) || DICT_EMPTY(pdict) ) {
365: status = EMPTY_DICTIONARY;
1.1.1.3 ! root 366: *item = NULL;
! 367: }
1.1 root 368: else {
369: *item = DICT_CURR_ITEM(pdict);
1.1.1.3 ! root 370: status = Dict_Delete( pdict, (void **)item );
1.1 root 371: }
372: return( (VDict_Status)status );
373: }
374:
375: VDict_Status
376: VDict_Get_Dict(
377: IN VDict v_dict,
378: OUT RDict ** r_dict
379: )
380: // used to transmit the dictionary back to the callee
381: // (In this demo program - for printing on the client side)
382: {
383: Dictionary * pdict = (Dictionary*) (v_dict);
384:
1.1.1.3 ! root 385: if (pdict == NULL) {
! 386: return(DICT_EMPTY_DICTIONARY);
! 387: }
1.1 root 388: else {
1.1.1.3 ! root 389: prinTree(0, 3, pdict->root, printRecord);
1.1 root 390:
391: *r_dict = RDict_Duplicate((RDict*)pdict);
392: // Duplication is done to avoid freeing the tree by
393: // the callee stub. This is a temporary fix, until we
394: // implement [allocate(dont_free)]!
395:
396: return(DICT_SUCCESS);
397: }
398: }
399:
400: /*************************************************************************/
401: /*** Server Utility Functions ***/
402: /*************************************************************************/
403:
404: void
405: Init_dict(Dictionary * dp)
406: {
407: Record* rp;
408:
1.1.1.2 root 409: rp = makeRecord((short)0, "jack_smith"); Dict_Insert(dp, rp);
410: rp = makeRecord((short)0, "john_doe"); Dict_Insert(dp, rp);
411: rp = makeRecord((short)1, "steve_johnson"); Dict_Insert(dp, rp);
412: rp = makeRecord((short)2, "debbie_jones"); Dict_Insert(dp, rp);
413: rp = makeRecord((short)0, "mike_jacobs"); Dict_Insert(dp, rp);
414: rp = makeRecord((short)2, "bill_jackson"); Dict_Insert(dp, rp);
415: rp = makeRecord((short)0, "jane_doe"); Dict_Insert(dp, rp);
416: rp = makeRecord((short)1, "james_doe"); Dict_Insert(dp, rp);
417: rp = makeRecord((short)1, "jean_doe"); Dict_Insert(dp, rp);
418: rp = makeRecord((short)0, "joana_smith"); Dict_Insert(dp, rp);
419: rp = makeRecord((short)1, "michael_jones"); Dict_Insert(dp, rp);
420: rp = makeRecord((short)0, "dianne_jackson"); Dict_Insert(dp, rp);
421: rp = makeRecord((short)0, "jacob_jacobson"); Dict_Insert(dp, rp);
1.1 root 422:
423: Dict_Print(dp, TAB_STOPS);
424: }
425:
426: /*************************************************************************/
427: /*** Play oriented Functions ... ***/
428: /*** (used to empty the tree and replace it by a tree of integers ***/
429: /*************************************************************************/
430:
431: VDict_Status
432: VDict_X_Dict(
433: IN VDict v_dict
434: )
435: // Empty the dictionary
436: {
437: RDict * prdict = (RDict*)v_dict;
438:
439: if (DICT_EMPTY(prdict))
440: return(DICT_EMPTY_DICTIONARY);
441:
442: RecordTreeNodeFree(prdict->root);
443: prdict->root = NULL;
1.1.1.3 ! root 444: return(DICT_SUCCESS);
1.1 root 445: }
446:
447: VDict_Status
448: VDict_I_Dict(
449: IN VDict v_dict,
450: IN short size
451: )
452: // Insert integers from 3 to a specified upper bound into the tree
453: {
454: RDict * prdict = (RDict*)v_dict;
455: Dict_Status status;
456: short i;
457:
458: // Insert (<num'>, "") for all num' s.t. 3 < num' < num
459: for (i=3; i < size; i++) {
1.1.1.3 ! root 460: status = VDict_Insert(prdict,
! 461: makeRecord(i, "<"));
! 462: }
1.1 root 463: return( (VDict_Status)status );
464: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.