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
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
|
/*
* @file var.h
* @brief MPR Universal Variable Type
* @copy default.m
*
* Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved.
* Copyright (c) Michael O'Brien, 1994-1995. All Rights Reserved.
*
* This software is distributed under commercial and open source licenses.
* You may use the GPL open source license described below or you may acquire
* a commercial license from Mbedthis Software. You agree to be fully bound
* by the terms of either license. Consult the LICENSE.TXT distributed with
* this software for full details.
*
* This software is open source; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See the GNU General Public License for more
* details at: http://www.mbedthis.com/downloads/gplLicense.html
*
* This program is distributed WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* This GPL license does NOT permit incorporating this software into
* proprietary programs. If you are unable to comply with the GPL, you must
* acquire a commercial license to use this software. Commercial licenses
* for this software and support services are available from Mbedthis
* Software at http://www.mbedthis.com
*
* @end
*/
/******************************* Documentation ********************************/
/*
* Variables can efficiently store primitive types and can hold references to
* objects. Objects can store properties which are themselves variables.
* Properties can be primitive data types, other objects or functions.
* Properties are indexed by a character name. A variable may store one of
* the following types:
*
* string, integer, integer-64bit, C function, C function with string args,
* Javascript function, Floating point number, boolean value, Undefined
* value and the Null value.
*
* Variables have names while objects may be referenced by multiple variables.
* Objects use reference counting for garbage collection.
*
* This module is not thread safe for performance and compactness. It relies
* on upper modules to provide thread synchronization as required. The API
* provides primitives to get variable/object references or to get copies of
* variables which will help minimize required lock times.
*/
#ifndef _h_MPR_VAR
#define _h_MPR_VAR 1
/********************************* Includes ***********************************/
#include "lib/ejs/miniMpr.h"
/********************************** Defines ***********************************/
/*
* Define VAR_DEBUG if you want to track objects. However, this code is not
* thread safe and you need to run the server single threaded.
*
* #define VAR_DEBUG 1
*/
#ifdef __cplusplus
extern "C" {
#endif
/*
* Forward declare types
*/
struct MprProperties;
struct MprVar;
/*
* Possible variable types. Don't use enum because we need to be able to
* do compile time conditional compilation on BLD_FEATURE_NUM_TYPE_ID.
*/
typedef int MprType;
#define MPR_TYPE_UNDEFINED 0 /* Undefined. No value has been set. */
#define MPR_TYPE_NULL 1 /* Value defined to be null. */
#define MPR_TYPE_BOOL 2 /* Boolean type. */
#define MPR_TYPE_CFUNCTION 3 /* C function or C++ method */
#define MPR_TYPE_FLOAT 4 /* Floating point number */
#define MPR_TYPE_INT 5 /* Integer number */
#define MPR_TYPE_INT64 6 /* 64-bit Integer number */
#define MPR_TYPE_OBJECT 7 /* Object reference */
#define MPR_TYPE_FUNCTION 8 /* JavaScript function */
#define MPR_TYPE_STRING 9 /* String (immutable) */
#define MPR_TYPE_STRING_CFUNCTION 10 /* C/C++ function with string args */
#define MPR_TYPE_PTR 11 /* C pointer */
/*
* Create a type for the default number type
* Config.h will define the default number type. For example:
*
* BLD_FEATURE_NUM_TYPE=int
* BLD_FEATURE_NUM_TYPE_ID=MPR_TYPE_INT
*/
/**
* Set to the type used for MPR numeric variables. Will equate to int, int64
* or double.
*/
typedef BLD_FEATURE_NUM_TYPE MprNum;
/**
* Set to the MPR_TYPE used for MPR numeric variables. Will equate to
* MPR_TYPE_INT, MPR_TYPE_INT64 or MPR_TYPE_FLOAT.
*/
#define MPR_NUM_VAR BLD_FEATURE_NUM_TYPE_ID
#define MPR_TYPE_NUM BLD_FEATURE_NUM_TYPE_ID
/*
* Return TRUE if a variable is a function type
*/
#define mprVarIsFunction(type) \
(type == MPR_TYPE_FUNCTION || type == MPR_TYPE_STRING_CFUNCTION || \
type == MPR_TYPE_CFUNCTION)
/*
* Return TRUE if a variable is a numeric type
*/
#define mprVarIsNumber(type) \
(type == MPR_TYPE_INT || type == MPR_TYPE_INT64 || type == MPR_TYPE_FLOAT)
/*
* Return TRUE if a variable is a boolean
*/
#define mprVarIsBoolean(type) \
(type == MPR_TYPE_BOOL)
#define mprVarIsString(type) \
(type == MPR_TYPE_STRING)
#define mprVarIsObject(type) \
(type == MPR_TYPE_OBJECT)
#define mprVarIsFloating(type) \
(type == MPR_TYPE_FLOAT)
#define mprVarIsPtr(type) \
(type == MPR_TYPE_PTR)
#define mprVarIsUndefined(var) \
((var)->type == MPR_TYPE_UNDEFINED)
#define mprVarIsNull(var) \
((var)->type == MPR_TYPE_NULL)
#define mprVarIsValid(var) \
(((var)->type != MPR_TYPE_NULL) && ((var)->type != MPR_TYPE_UNDEFINED))
#define MPR_VAR_MAX_RECURSE 5 /* Max object loops */
#if BLD_FEATURE_SQUEEZE
#define MPR_MAX_VAR 64 /* Max var full name */
#else
#define MPR_MAX_VAR 512
#endif
#ifndef __NO_PACK
#pragma pack(2)
#endif /* _NO_PACK */
/*
* Function signatures
*/
typedef int MprVarHandle;
typedef int (*MprCFunction)(MprVarHandle userHandle, int argc,
struct MprVar **argv);
typedef int (*MprStringCFunction)(MprVarHandle userHandle, int argc,
char **argv);
/*
* Triggers
*/
typedef enum {
MPR_VAR_WRITE, /* This property is being updated */
MPR_VAR_READ, /* This property is being read */
MPR_VAR_CREATE_PROPERTY, /* A property is being created */
MPR_VAR_DELETE_PROPERTY, /* A property is being deleted */
MPR_VAR_DELETE /* This object is being deleted */
} MprVarTriggerOp;
/*
* Trigger function return codes.
*/
typedef enum {
MPR_TRIGGER_ABORT, /* Abort the current operation */
MPR_TRIGGER_USE_NEW_VALUE, /* Proceed and use the newValue */
MPR_TRIGGER_PROCEED /* Proceed with the operation */
} MprVarTriggerStatus;
/*
* The MprVarTrigger arguments have the following meaning:
*
* op The operation being performed. See MprVarTriggerOp.
* parentProperties Pointer to the MprProperties structure.
* vp Pointer to the property that registered the trigger.
* newValue New value (see below for more details).
* copyDepth Specify what data items to copy.
*
* For VAR_READ, newVar is set to a temporary variable that the trigger
* function may assign a value to be returned instead of the actual
* property value.
* For VAR_WRITE, newValue holds the new value. The old existing value may be
* accessed via vp.
* For DELETE_PROPERTY, vp is the property being deleted. newValue is null.
* For ADD_PROPERTY, vp is set to the property being added and newValue holds
* the new value.
*/
typedef MprVarTriggerStatus (*MprVarTrigger)(MprVarTriggerOp op,
struct MprProperties *parentProperties, struct MprVar *vp,
struct MprVar *newValue, int copyDepth);
/*
* mprCreateFunctionVar flags
*/
/** Use the alternate handle on function callbacks */
#define MPR_VAR_ALT_HANDLE 0x1
/** Use the script handle on function callbacks */
#define MPR_VAR_SCRIPT_HANDLE 0x2
/*
* Useful define for the copyDepth argument
*/
/** Don't copy any data. Copy only the variable name */
#define MPR_NO_COPY 0
/** Copy strings. Increment object reference counts. */
#define MPR_SHALLOW_COPY 1
/** Copy strings and do complete object copies. */
#define MPR_DEEP_COPY 2
/*
* GetFirst / GetNext flags
*/
/** Step into data properties. */
#define MPR_ENUM_DATA 0x1
/** Step into functions properties. */
#define MPR_ENUM_FUNCTIONS 0x2
/*
* Collection type to hold properties in an object
*/
typedef struct MprProperties { /* Collection of properties */
#if VAR_DEBUG
struct MprProperties *next; /* Linked list */
struct MprProperties *prev; /* Linked list */
char name[32]; /* Debug name */
#endif
struct MprVar **buckets; /* Hash chains */
int numItems; /* Total count of items */
int numDataItems; /* Enumerable data items */
uint hashSize : 8; /* Size of the hash table */
uint refCount : 8; /* References to this property*/
uint deleteProtect : 8; /* Don't recursively delete */
uint visited : 8; /* Node has been processed */
} MprProperties;
/*
* Universal Variable Type
*/
typedef struct MprVar {
MprStr name; /* Property name */
MprStr fullName; /* Full object name */
MprProperties *properties; /* Pointer to properties */
/*
* Packed bit field
*/
MprType type : 8; /* Selector into union */
uint bucketIndex : 8; /* Copy of bucket index */
uint flags : 5; /* Type specific flags */
uint allocatedData : 1; /* Data needs freeing */
uint readonly : 1; /* Unmodifiable */
uint deleteProtect : 1; /* Don't recursively delete */
uint visited : 1; /* Node has been processed */
uint allocatedVar : 1; /* Var needs freeing */
uint spare : 6; /* Unused */
struct MprVar *forw; /* Hash table linkage */
MprVarTrigger trigger; /* Trigger function */
#if UNUSED && KEEP
struct MprVar *baseClass; /* Pointer to class object */
#endif
MprProperties *parentProperties; /* Pointer to parent object */
/*
* Union of primitive types. When debugging on Linux, don't use unions
* as the gdb debugger can't display them.
*/
#if !BLD_DEBUG && !LINUX && !VXWORKS
union {
#endif
int boolean; /* Use int for speed */
#if BLD_FEATURE_FLOATING_POINT
double floating;
#endif
int integer;
#if BLD_FEATURE_INT64
int64 integer64;
#endif
struct { /* Javascript functions */
MprArray *args; /* Null terminated */
char *body;
} function;
struct { /* Function with MprVar args */
MprCFunction fn;
void *thisPtr;
} cFunction;
struct { /* Function with string args */
MprStringCFunction fn;
void *thisPtr;
} cFunctionWithStrings;
MprStr string; /* Allocated string */
void *ptr; /* C pointer */
#if !BLD_DEBUG && !LINUX && !VXWORKS
};
#endif
} MprVar;
/*
* Define a field macro so code an use numbers in a "generic" fashion.
*/
#if MPR_NUM_VAR == MPR_TYPE_INT || DOXYGEN
/* Default numeric type */
#define mprNumber integer
#endif
#if MPR_NUM_VAR == MPR_TYPE_INT64
/* Default numeric type */
#define mprNumber integer64
#endif
#if MPR_NUM_VAR == MPR_TYPE_FLOAT
/* Default numeric type */
#define mprNumber floating
#endif
typedef BLD_FEATURE_NUM_TYPE MprNumber;
#ifndef __NO_PACK
#pragma pack()
#endif /* __NO_PACK */
/********************************* Prototypes *********************************/
/*
* Variable constructors and destructors
*/
extern MprVar mprCreateObjVar(const char *name, int hashSize);
extern MprVar mprCreateBoolVar(bool value);
extern MprVar mprCreateCFunctionVar(MprCFunction fn, void *thisPtr,
int flags);
extern MprVar mprCreatePtrVar(void *ptr, const char *name);
#if BLD_FEATURE_FLOATING_POINT
extern MprVar mprCreateFloatVar(double value);
#endif
extern MprVar mprCreateIntegerVar(int value);
#if BLD_FEATURE_INT64
extern MprVar mprCreateInteger64Var(int64 value);
#endif
extern MprVar mprCreateFunctionVar(char *args, char *body, int flags);
extern MprVar mprCreateNullVar(void);
extern MprVar mprCreateNumberVar(MprNumber value);
extern MprVar mprCreateStringCFunctionVar(MprStringCFunction fn,
void *thisPtr, int flags);
extern MprVar mprCreateStringVar(const char *value, bool allocate);
extern MprVar mprCreateUndefinedVar(void);
extern bool mprDestroyVar(MprVar *vp);
extern bool mprDestroyAllVars(MprVar* vp);
extern MprType mprGetVarType(MprVar *vp);
/*
* Copy
*/
extern void mprCopyVar(MprVar *dest, MprVar *src, int copyDepth);
extern void mprCopyVarValue(MprVar *dest, MprVar src, int copyDepth);
extern MprVar *mprDupVar(MprVar *src, int copyDepth);
/*
* Manage vars
*/
extern MprVarTrigger
mprAddVarTrigger(MprVar *vp, MprVarTrigger fn);
extern int mprGetVarRefCount(MprVar *vp);
extern void mprSetVarDeleteProtect(MprVar *vp, int deleteProtect);
extern void mprSetVarFullName(MprVar *vp, char *name);
extern void mprSetVarReadonly(MprVar *vp, int readonly);
extern void mprSetVarName(MprVar *vp, char *name);
/*
* Create properties and return a reference to the property.
*/
extern MprVar *mprCreateProperty(MprVar *obj, const char *property,
MprVar *newValue);
extern MprVar *mprCreatePropertyValue(MprVar *obj, const char *property,
MprVar newValue);
extern int mprDeleteProperty(MprVar *obj, const char *property);
/*
* Get/Set properties. Set will update/create.
*/
extern MprVar *mprGetProperty(MprVar *obj, const char *property, MprVar *value);
extern MprVar *mprSetProperty(MprVar *obj, const char *property, MprVar *value);
extern MprVar *mprSetPropertyValue(MprVar *obj, const char *property, MprVar value);
/*
* Directly read/write property values (the property must already exist)
* For mprCopyProperty, mprDestroyVar must always called on the var.
*/
extern int mprReadProperty(MprVar *prop, MprVar *value);
extern int mprWriteProperty(MprVar *prop, MprVar *newValue);
extern int mprWritePropertyValue(MprVar *prop, MprVar newValue);
/*
* Copy a property. NOTE: reverse of most other args: (dest, src)
*/
extern int mprCopyProperty(MprVar *dest, MprVar *prop, int copyDepth);
/*
* Enumerate properties
*/
extern MprVar *mprGetFirstProperty(MprVar *obj, int includeFlags);
extern MprVar *mprGetNextProperty(MprVar *obj, MprVar *currentProperty,
int includeFlags);
/*
* Query properties characteristics
*/
extern int mprGetPropertyCount(MprVar *obj, int includeFlags);
/*
* Conversion routines
*/
extern MprVar mprParseVar(char *str, MprType prefType);
extern MprNum mprVarToNumber(MprVar *vp);
extern int mprVarToInteger(MprVar *vp);
#if BLD_FEATURE_INT64
extern int64 mprVarToInteger64(MprVar *vp);
#endif
extern bool mprVarToBool(MprVar *vp);
#if BLD_FEATURE_FLOATING_POINT
extern double mprVarToFloat(MprVar *vp);
#endif
extern void mprVarToString(char** buf, int size, char *fmt, MprVar *vp);
/*
* Parsing and utility routines
*/
extern MprNum mprParseNumber(char *str);
extern int mprParseInteger(char *str);
#if BLD_FEATURE_INT64
extern int64 mprParseInteger64(char *str);
#endif
#if BLD_FEATURE_FLOATING_POINT
extern double mprParseFloat(char *str);
extern bool mprIsInfinite(double f);
extern bool mprIsNan(double f);
#endif
#if VAR_DEBUG
extern void mprPrintObjects(char *msg);
extern void mprPrintObjRefCount(MprVar *vp);
#endif
#ifdef __cplusplus
}
#endif
/*****************************************************************************/
#endif /* _h_MPR_VAR */
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim:tw=78
* vim600: sw=4 ts=4 fdm=marker
* vim<600: sw=4 ts=4
*/
|