3 MPDM - Minimum Profit Data Manager
4 Copyright (C) 2003/2011 Angel Ortega <angel@triptico.com>
6 mpdm_v.c - Basic value management
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 http://www.triptico.com
38 /* control structure */
40 struct mpdm_control
*mpdm
= NULL
;
45 static void cleanup_value(mpdm_t v
)
48 /* collapse multiple values */
49 if (v
->flags
& MPDM_MULTIPLE
) {
52 for (n
= 0; n
< mpdm_size(v
); n
++)
53 mpdm_unref(mpdm_aget(v
, n
));
56 /* free data if needed */
57 if (v
->data
!= NULL
&& v
->flags
& MPDM_FREE
) {
58 free((void *) v
->data
);
64 if (!(v
->flags
& MPDM_NONDYN
))
69 static void destroy_value(mpdm_t v
)
70 /* destroys a value */
77 * mpdm_init - Initializes a value.
78 * @v: the value to initialize
80 * @data: pointer to real data
83 * Initializes a value.
85 * This function is normally not directly used; use any of the type
86 * creation macros instead.
89 mpdm_t
mpdm_init(mpdm_t v
, int flags
, const void *data
, int size
)
91 /* if v is NULL crash JUST NOW */
104 * mpdm_new - Creates a new value.
106 * @data: pointer to real data
107 * @size: size of data
109 * Creates a new value. @flags is an or-ed set of flags, @data is a
110 * pointer to the data the value will store and @size the size of these
111 * data (if value is to be a multiple one, @size is a number of elements,
112 * or a number of bytes otherwise).
114 * This function is normally not directly used; use any of the type
115 * creation macros instead.
118 mpdm_t
mpdm_new(int flags
, const void *data
, int size
)
120 return mpdm_init(malloc(sizeof(struct mpdm_val
)),
121 flags
& ~MPDM_NONDYN
, data
, size
);
126 * mpdm_ref - Increments the reference count of a value.
129 * Increments the reference count of a value.
132 mpdm_t
mpdm_ref(mpdm_t v
)
142 * mpdm_unref - Decrements the reference count of a value.
145 * Decrements the reference count of a value. If the reference
146 * count of the value reaches 0, it's destroyed.
149 mpdm_t
mpdm_unref(mpdm_t v
)
165 * mpdm_unrefnd - Decrements the reference count of a value, without destroy.
168 * Decrements the reference count of a value, without destroying
169 * the value if it's unreferenced.
172 mpdm_t
mpdm_unrefnd(mpdm_t v
)
182 * mpdm_size - Returns the size of an element.
185 * Returns the size of an element. It does not change the
186 * reference count of the value.
189 int mpdm_size(const mpdm_t v
)
193 /* NULL values have no size */
202 * mpdm_clone - Creates a clone of a value.
205 * Creates a clone of a value. If the value is multiple, a new value will
206 * be created containing clones of all its elements; otherwise,
207 * the same unchanged value is returned.
210 mpdm_t
mpdm_clone(const mpdm_t v
)
214 if (MPDM_IS_ARRAY(v
) && !MPDM_IS_EXEC(v
))
224 * mpdm_root - Returns the root hash.
226 * Returns the root hash. This hash is stored internally and can be used
227 * as a kind of global symbol table.
230 mpdm_t
mpdm_root(void)
232 if (mpdm
->root
== NULL
)
233 mpdm
->root
= mpdm_ref(MPDM_H(0));
240 * mpdm_set_ival - Sets the integer value.
244 * Sets the integer value for @v. It does not change
245 * the reference count of @v.
247 mpdm_t
mpdm_set_ival(mpdm_t v
, int ival
)
248 /* sets an integer value to a value */
250 v
->flags
|= MPDM_IVAL
;
258 * mpdm_set_rval - Sets the real value.
262 * Sets the real value for @v. It does not change
263 * the reference count of @v.
265 mpdm_t
mpdm_set_rval(mpdm_t v
, double rval
)
266 /* sets a real value to a value */
268 v
->flags
|= MPDM_RVAL
;
276 * mpdm_void - Refs then unrefs a value.
279 * References and unreferences a value. To be used to receive
280 * the output of mpdm_exec() in case of it being void (i.e.
281 * its return value ignored).
283 void mpdm_void(mpdm_t v
)
291 * mpdm_is_null - Returns 1 if a value is NULL.
294 * Returns 1 if a value is NULL. The reference count is touched.
296 int mpdm_is_null(mpdm_t v
)
301 r
= v
== NULL
? 1 : 0;
309 * mpdm_exec - Executes an executable value.
311 * @args: the arguments
314 * Executes an executable value. If @c is a scalar value, its data
315 * should be a pointer to a directly executable C function with a
316 * prototype of mpdm_t func(mpdm_t args, mpdm_t ctxt); if it's a multiple
317 * one, the first value's data should be a pointer to a directly executable
318 * C function with a prototype of
319 * mpdm_t func(mpdm_t b, mpdm_t args, mpdm_t ctxt) and
320 * the second value will be passed as the @b argument. This value is used
321 * to store bytecode or so when implementing virtual machines or compilers.
322 * The @ctxt is meant to be used as a special context to implement local
323 * symbol tables and such. Its meaning is free and can be NULL.
325 * Returns the return value of the code. If @c is NULL or not executable,
329 mpdm_t
mpdm_exec(mpdm_t c
, mpdm_t args
, mpdm_t ctxt
)
337 if (c
!= NULL
&& (c
->flags
& MPDM_EXEC
)) {
339 if (c
->flags
& MPDM_MULTIPLE
) {
341 mpdm_t(*func
) (mpdm_t
, mpdm_t
, mpdm_t
);
343 /* value is multiple; first element is the
344 3 argument version of the executable function,
345 next its optional additional information,
346 the arguments and the context */
350 (mpdm_t(*)(mpdm_t
, mpdm_t
, mpdm_t
)) (x
->data
)) != NULL
)
351 r
= func(mpdm_aget(c
, 1), args
, ctxt
);
354 mpdm_t(*func
) (mpdm_t
, mpdm_t
);
356 /* value is scalar; c is the 2 argument
357 version of the executable function */
358 if ((func
= (mpdm_t(*)(mpdm_t
, mpdm_t
)) (c
->data
)) != NULL
)
359 r
= func(args
, ctxt
);
371 mpdm_t
mpdm_exec_1(mpdm_t c
, mpdm_t a1
, mpdm_t ctxt
)
374 mpdm_t a
= MPDM_LA(1);
379 r
= mpdm_exec(c
, a
, ctxt
);
387 mpdm_t
mpdm_exec_2(mpdm_t c
, mpdm_t a1
, mpdm_t a2
, mpdm_t ctxt
)
390 mpdm_t a
= MPDM_LA(2);
396 r
= mpdm_exec(c
, a
, ctxt
);
404 mpdm_t
mpdm_exec_3(mpdm_t c
, mpdm_t a1
, mpdm_t a2
, mpdm_t a3
, mpdm_t ctxt
)
407 mpdm_t a
= MPDM_LA(3);
414 r
= mpdm_exec(c
, a
, ctxt
);
422 mpdm_t
mpdm_xnew(mpdm_t(*a1
) (mpdm_t
, mpdm_t
, mpdm_t
), mpdm_t a2
)
427 x
->flags
|= MPDM_EXEC
;
431 mpdm_aset(x
, MPDM_X(a1
), 0);
440 mpdm_t
mpdm_new_copy(int flags
, void *ptr
, int size
)
445 char *ptr2
= malloc(size
);
446 memcpy(ptr2
, ptr
, size
);
448 r
= mpdm_new(MPDM_FREE
| flags
, ptr2
, size
);
455 static mpdm_t
MPDM(const mpdm_t args
, mpdm_t ctxt
)
456 /* accesor / mutator for MPDM internal data */
462 v
= mpdm_aget(args
, 0);
468 if ((w
= mpdm_hget_s(v
, L
"hash_buckets")) != NULL
)
469 mpdm
->hash_buckets
= mpdm_ival(w
);
472 /* now collect all information */
477 mpdm_hset_s(v
, L
"version", MPDM_MBS(VERSION
));
478 mpdm_hset_s(v
, L
"count", MPDM_I(mpdm
->count
));
479 mpdm_hset_s(v
, L
"hash_buckets", MPDM_I(mpdm
->hash_buckets
));
488 extern char **environ
;
490 static mpdm_t
build_env(void)
491 /* builds a hash with the environment */
494 mpdm_t e
= MPDM_H(0);
498 for (ptr
= environ
; *ptr
!= NULL
; ptr
++) {
499 char *eq
= strchr(*ptr
, '=');
504 k
= MPDM_NMBS((*ptr
), eq
- (*ptr
));
505 v
= MPDM_MBS(eq
+ 1);
518 * mpdm_startup - Initializes MPDM.
520 * Initializes the Minimum Profit Data Manager. Returns 0 if
521 * everything went OK.
523 int mpdm_startup(void)
525 /* do the startup only unless done beforehand */
528 if ((mpdm
= malloc(sizeof(struct mpdm_control
))) == NULL
)
532 memset(mpdm
, '\0', sizeof(struct mpdm_control
));
534 /* sets the defaults */
535 mpdm
->hash_buckets
= 31;
537 /* sets the locale */
538 if (setlocale(LC_ALL
, "") == NULL
)
539 setlocale(LC_ALL
, "C");
543 /* store the MPDM() function */
544 mpdm_hset_s(mpdm_root(), L
"MPDM", MPDM_X(MPDM
));
546 /* store the ENV hash */
547 mpdm_hset_s(mpdm_root(), L
"ENV", build_env());
550 /* everything went OK */
556 * mpdm_shutdown - Shuts down MPDM.
558 * Shuts down MPDM. No MPDM functions should be used from now on.
560 void mpdm_shutdown(void)
566 * MPDM_A - Creates an array value.
567 * @n: Number of elements
569 * Creates a new array value with @n elements.
572 /** mpdm_t MPDM_A(int n); */
576 * MPDM_H - Creates a hash value.
577 * @n: Number of buckets in the hash (0: use default)
579 * Creates a new hash value with @n buckets. The number
580 * of buckets must be a prime number. If @n is 0, an
581 * optimal number of buckets will be used.
584 /** mpdm_t MPDM_H(int n); */
588 * MPDM_LS - Creates a string value from a literal string.
589 * @wcs: the wide character string
591 * Creates a new string value from a literal, wide character string.
592 * A pointer to the string will be stored in the value (not a copy).
595 /** mpdm_t MPDM_LS(wchar_t * wcs); */
599 * MPDM_S - Creates a string value from a string.
600 * @wcs: the wide character string
602 * Creates a new string value from a wide character string. The value
603 * will store a copy of the string that will be freed on destruction.
606 /** mpdm_t MPDM_S(wchar_t * wcs); */
610 * MPDM_NS - Creates a string value from a string, with size.
611 * @wcs: the wide character string
612 * @s: the size in chars the string will hold
614 * Creates a new string value with a copy of the first @s characters
615 * from the @wcs string.
618 /** mpdm_t MPDM_NS(wchar_t * wcs, int s); */
622 * MPDM_ENS - Creates a string value from an external string, with size.
623 * @wcs: the external wide character string
624 * @s: the size in chars the string will hold
626 * Creates a new string value with size @s. The @wcs string must be
627 * a dynamic value (i.e. allocated by malloc()) that will be freed on
631 /** mpdm_t MPDM_ENS(wchar_t * wcs, int s); */
635 * MPDM_I - Creates an integer value.
638 * Creates a new integer value. MPDM integers are strings.
641 /** mpdm_t MPDM_I(int i); */
645 * MPDM_R - Creates a real value.
646 * @r: the real number
648 * Creates a new real value. MPDM integers are strings.
651 /** mpdm_t MPDM_R(double r); */
655 * MPDM_F - Creates a file value.
656 * @f: the file descriptor
658 * Creates a new file value.
661 /** mpdm_t MPDM_F(FILE * f); */
665 * MPDM_MBS - Creates a string value from a multibyte string.
666 * @mbs: the multibyte string
668 * Creates a new string value from a multibyte string, that will be
669 * converted to wcs by mpdm_mbstowcs().
672 /** mpdm_t MPDM_MBS(char * mbs); */
676 * MPDM_NMBS - Creates a string value from a multibyte string, with size.
677 * @mbs: the multibyte string
680 * Creates a new string value with the first @s characters from the @mbs
681 * multibyte string, that will be converted to wcs by mpdm_mbstowcs().
684 /** mpdm_t MPDM_NMBS(char * mbs, int s); */
688 * MPDM_2MBS - Creates a multibyte string value from a wide char string.
689 * @wcs: the wide char string
691 * Creates a multibyte string value from the @wcs wide char string,
692 * converting it by mpdm_wcstombs(). Take note that multibyte string values
693 * are not properly strings, so they cannot be used for string comparison
697 /** mpdm_t MPDM_2MBS(wchar_t * wcs); */
701 * MPDM_X - Creates a new executable value.
702 * @func: the C code function
704 * Creates a new executable value given a pointer to the @func C code function.
705 * The function must receive an mpdm_t array value (that will hold their
706 * arguments) and return another one.
709 /** mpdm_t MPDM_X(mpdm_t (* func)(mpdm_t args)); */
713 * MPDM_C - Creates a new value with a copy of a buffer.
714 * @flags: additional flags
715 * @ptr: pointer to data
718 * Create a new value with a copy of a buffer. The value will store a copy
719 * of @ptr and have the additional @flags.
722 /** mpdm_t MPDM_C(int flags, void *ptr, int size); */
726 * MPDM_IS_ARRAY - Tests if a value is an array.
729 * Returns non-zero if @v is an array.
731 /** int MPDM_IS_ARRAY(mpdm_t v); */
735 * MPDM_IS_HASH - Tests if a value is a hash.
738 * Returns non-zero if @v is a hash.
740 /** int MPDM_IS_HASH(mpdm_t v); */
744 * MPDM_IS_EXEC - Tests if a value is executable.
747 * Returns non-zero if @v is executable.
749 /** int MPDM_IS_EXEC(mpdm_t v); */
753 * MPDM_IS_STRING - Tests if a value is a string.
756 * Returns non-zero if @v is a string.
758 /** int MPDM_IS_STRING(mpdm_t v); */