50
51
static INT bool_to_int(BOOLEAN);
51
52
static void clear_pv_indiseq(INDISEQ seq);
52
53
static void clear_pvalue(PVALUE val);
53
55
static PVALUE create_pvalue_from_keynum_impl(INT i, INT ptype);
54
static PVALUE create_pvalue_from_key_impl(STRING key, INT ptype);
56
static PVALUE create_pvalue_from_key_impl(CNSTRING key, INT ptype);
55
57
static PVALUE create_pvalue_from_record(RECORD rec, INT ptype);
56
static BOOLEAN eq_pstrings(PVALUE val1, PVALUE val2);
58
/* static BOOLEAN eq_pstrings(PVALUE val1, PVALUE val2); */
57
59
static int float_to_int(float f);
58
60
static void free_float_pvalue(PVALUE val);
61
static BOOLEAN is_record_pvaltype(INT valtype);
59
62
static OBJECT pvalue_copy(OBJECT obj, int deep);
60
63
static void pvalue_destructor(VTABLE *obj);
61
static void table_pvcleaner(ENTRY ent);
64
static void table_pvcleaner(CNSTRING key, UNION uval);
63
66
/*********************************************
65
68
*********************************************/
70
/* These names are offset by the number of their type */
71
/* PFLOAT == 4, so "PFLOAT" must be at array offset 4 */
67
72
static char *ptypes[] = {
68
"PNONE", "PANY", "PINT", "PLONG", "PFLOAT", "PBOOL", "PSTRING",
73
"?", "PNULL", "PINT", "PLONG", "PFLOAT", "PBOOL", "PSTRING",
69
74
"PGNODE", "PINDI", "PFAM", "PSOUR", "PEVEN", "POTHR", "PLIST",
75
"PTABLE", "PSET", "PARRAY"
72
77
static struct tag_vtable vtable_for_pvalue = {
106
111
set_pvalue (PVALUE val, INT type, VPTR value)
108
if (type == ptype(val) && value == pvalue(val)) {
113
if (type == ptype(val) && value == pvalvv(val)) {
109
114
/* self-assignment */
115
/* already have the value, or hold the pointer & reference */
119
/* record pvalues each have their own RECORD on the heap */
112
121
clear_pvalue(val);
114
123
/* sanity check */
121
129
/* types that don't simply assign pointer */
130
/* old refers to value passed in */
131
/* new refers to newly allocated copy to set */
125
/* always copies string so caller doesn't have to */
127
value = (VPTR) strsave((STRING) value);
135
/* always copies string so caller doesn't have to */
137
STRING strold = (STRING)value;
138
STRING strnew = strsave(strold);
145
float valold, *ptrnew;
132
147
/* floats don't fit into VPTR, so we're using heap copies */
133
float *ptr = (float *)stdalloc(sizeof(*ptr));
134
*ptr = *(float *)value;
148
valold = *(float *)value;
149
/* allocate new pointer & copy float into place */
150
ptrnew = (float *)stdalloc(sizeof(*ptrnew));
140
157
ptype(val) = type;
160
if (is_record_pvaltype(type)) {
161
RECORD rec = pvalue_to_record(val);
143
167
/* reference counted types and so forth */
347
342
delete_pvalue(val);
349
344
/*========================================
350
* delete_pvalue_wrapper -- Delete the pvalue
351
* shell, but not the value inside
352
* Created: 2003-02-02 (Perry Rapp)
345
* remove_node_and_delete_pvalue -- Remove
346
* node inside pvalue, and delete pvalue
353
347
*======================================*/
355
delete_pvalue_wrapper (PVALUE val)
349
remove_node_and_delete_pvalue (PVALUE * pval)
358
pvalue(val) = 0; /* remove pointer to payload */
354
node = pvalue_to_node(vl);
355
pvalvv(vl) = 0; /* remove pointer to payload */
361
361
/*========================================
362
362
* delete_pvalue -- Delete a program value
409
412
* Created: 2000/12/30, Perry Rapp
410
413
*===================================================*/
412
create_pvalue_from_indi_key (STRING key)
415
create_pvalue_from_indi_key (CNSTRING key)
414
417
return create_pvalue_from_key_impl(key, PINDI);
416
419
/*=====================================================
420
* create_pvalue_from_fam_key
422
*===================================================*/
424
create_pvalue_from_fam_key (STRING key)
426
return create_pvalue_from_key_impl(key, PFAM);
428
/*=====================================================
417
429
* create_pvalue_from_cel
418
430
* Created: 2002/02/17, Perry Rapp
419
431
*===================================================*/
421
create_pvalue_from_cel (CACHEEL cel)
433
create_pvalue_from_cel (INT type, CACHEEL cel)
423
return create_pvalue(PINDI, cel);
436
RECORD rec = cel ? get_record_for_cel(cel) : 0;
437
val = create_pvalue(type, rec);
438
release_record(rec); /* ownership transferred to pvalue */
425
441
/*=====================================================
426
442
* create_pvalue_from_indi_keynum -- Return indi as pvalue
485
501
/*=====================================================
486
502
* create_pvalue_from_record -- Create pvalue from any node
488
* Created: 2001/03/20, Perry Rapp
504
* If rec is not null, it is given to new pvalue to own
489
505
*===================================================*/
491
507
create_pvalue_from_record (RECORD rec, INT ptype)
493
CACHEEL cel = rec ? record_to_cacheel(rec) : NULL;
494
return create_pvalue(ptype, cel);
509
/* record pvalues simply point to their heap-alloc'd record */
510
return create_pvalue(ptype, rec);
496
512
/*====================================================
497
513
* create_pvalue_from_keynum_impl -- Create pvalue for any type
558
575
ASSERT(val1 && val2);
559
576
if (ptype(val1) == ptype(val2)) return;
560
if (ptype(val1) == PANY && pvalue(val1) == NULL)
577
if (ptype(val1) == PNULL)
561
578
ptype(val1) = ptype(val2);
562
if (ptype(val2) == PANY && pvalue(val2) == NULL)
579
if (ptype(val2) == PNULL)
563
580
ptype(val2) = ptype(val1);
564
581
if (ptype(val1) == ptype(val2)) return;
565
if (ptype(val1) == PINT && pvalue(val1) == 0 && !is_numeric_pvalue(val2))
582
if (ptype(val1) == PINT && pvalue_to_int(val1) == 0 && !is_numeric_pvalue(val2))
566
583
ptype(val1) = ptype(val2);
567
if (ptype(val2) == PINT && pvalue(val2) == 0 && !is_numeric_pvalue(val1))
584
if (ptype(val2) == PINT && pvalue_to_int(val2) == 0 && !is_numeric_pvalue(val1))
568
585
ptype(val2) = ptype(val1);
569
586
if (ptype(val1) == ptype(val2)) return;
570
587
if (is_numeric_pvalue(val1) && is_numeric_pvalue(val2)) {
592
609
if (type == PBOOL) {
593
610
/* Anything is convertible to PBOOL */
594
BOOLEAN boo = (pvalue(val) != NULL);
611
BOOLEAN boo = (pvalvv(val) != NULL);
595
612
set_pvalue_bool(val, boo);
598
/* Anything is convertible to PANY */
615
/* Anything is convertible to PNULL */
599
616
/* Perry, 2002.02.16: This looks suspicious to me, but I
600
617
don't know how it is used -- it might be used in some
601
618
eq_conform_pvalues call(s) ? */
607
/* PANY or PINT with NULL (0) value is convertible to any scalar (1995.07.31) */
608
if ((ptype(val) == PANY || ptype(val) == PINT) && pvalue(val) == NULL) {
624
/* PNULL or PINT with NULL (0) value is convertible to any scalar (1995.07.31) */
625
if (ptype(val) == PNULL || (ptype(val) == PINT && pvalue_to_int(val) == 0)) {
609
626
if (type == PSET || type == PTABLE || type == PLIST) goto bad;
611
628
INTs convert to FLOATs numerically further down, no special
728
753
BOOLEAN rel = FALSE;
729
754
if(val1 && val2 && (ptype(val1) == ptype(val2))) {
730
755
switch (ptype(val1)) {
756
/* types with value semantics do value comparison */
758
v1 = pvalue_to_string(val1);
759
v2 = pvalue_to_string(val2);
734
760
if(v1 && v2) rel = eqstr(v1, v2);
735
761
else rel = (v1 == v2);
738
764
rel = (pvalue_to_float(val1) == pvalue_to_float(val2));
767
rel = (pvalue_to_int(val1) == pvalue_to_int(val2));
770
rel = (pvalue_to_bool(val1) == pvalue_to_bool(val2));
772
case PINDI: case PFAM: case PSOUR: case PEVEN: case POTHR:
775
rec1 = pvalue_to_record(val1);
776
rec2 = pvalue_to_record(val2);
777
if (rec1 && rec2) rel = eqstrn(nzkey(rec1),nzkey(rec2),MAXKEYWIDTH+1);
778
else rel = (rec1 == rec2);
740
781
/* for everything else, just compare value pointer */
742
rel = (pvalue(val1) == pvalue(val2));
783
rel = (pvalvv(val1) == pvalvv(val2));
913
953
zs_appf(zstr, _pl("%d record", "%d records", n), n);
958
ARRAY arr = pvalue_to_array(val);
959
INT n = get_array_size(arr);
960
zs_appf(zstr, _pl("%d element", "%d elements", n), n);
917
zs_appf(zstr, "%p", pvalue(val));
964
zs_appf(zstr, "%p", pvalvv(val));
920
967
zs_appc(zstr, '>');
923
970
/*==================================
924
* PANY: pvalue with no content
971
* PNULL: pvalue with no content
925
972
*================================*/
927
974
create_pvalue_any (void)
929
return create_pvalue(PANY, NULL);
976
return create_pvalue(PNULL, NULL);
931
978
/*==================================
932
* PBOOL: pvalue containing a boolean
979
* PINT: pvalue containing an int
933
980
*================================*/
935
create_pvalue_from_bool (BOOLEAN bval)
982
create_pvalue_from_int (INT ival)
937
return create_pvalue_from_int(bval);
984
return create_pvalue(PINT, (VPTR) ival);
940
set_pvalue_bool (PVALUE val, BOOLEAN bnum)
987
set_pvalue_int (PVALUE val, INT inum)
942
set_pvalue(val, PBOOL, (VPTR)bnum);
989
set_pvalue(val, PINT, (VPTR)inum);
945
pvalue_to_bool (PVALUE val)
992
pvalue_to_int (PVALUE val)
947
return (BOOLEAN)pvalue(val);
994
return (INT)pvalvv(val);
949
996
/*==================================
950
997
* PFLOAT: pvalue containing a float
965
1012
pvalue_to_float (PVALUE val)
967
1014
/* TODO: change when ptag goes to UNION */
968
return *(float*)pvalue(val);
971
pvalue_to_pfloat (PVALUE val)
973
/* convenience for math */
974
/* TODO: change when ptag goes to UNION */
975
return (float*)pvalue(val);
1015
return *(float*)pvalvv(val);
1017
/*==================================
1018
* PBOOL: pvalue containing a boolean
1019
*================================*/
1021
create_pvalue_from_bool (BOOLEAN bval)
1023
return create_pvalue_from_int(bval);
1026
set_pvalue_bool (PVALUE val, BOOLEAN bnum)
1028
set_pvalue(val, PBOOL, (VPTR)bnum);
1031
pvalue_to_bool (PVALUE val)
1033
return (BOOLEAN)pvalvv(val);
1035
/*==================================
1036
* PSTRING: pvalue containing a string
1037
*================================*/
1039
create_pvalue_from_string (CNSTRING str)
1041
return create_pvalue(PSTRING, (VPTR)str);
1044
set_pvalue_string (PVALUE val, CNSTRING str)
1046
set_pvalue(val, PSTRING, (VPTR)str); /* makes new copy of string */
1049
pvalue_to_string (PVALUE val)
1051
return (STRING)pvalvv(val);
977
1053
/*==================================
978
1054
* PGNODE: pvalue containing a GEDCOM node
991
1067
pvalue_to_node (PVALUE val)
993
return (NODE)pvalue(val);
995
/*==================================
996
* PINT: pvalue containing an int
997
*================================*/
999
create_pvalue_from_int (INT ival)
1001
return create_pvalue(PINT, (VPTR) ival);
1004
set_pvalue_int (PVALUE val, INT inum)
1006
set_pvalue(val, PINT, (VPTR)inum);
1009
pvalue_to_int (PVALUE val)
1011
return (INT)pvalue(val);
1014
pvalue_to_pint (PVALUE val)
1016
/* convenience for math */
1017
return (INT *)&pvalue(val);
1019
/*==================================
1020
* ARRAY: pvalue containing an array
1021
*================================*/
1023
pvalue_to_array (PVALUE val)
1025
return (ARRAY)pvalue(val);
1027
/*==================================
1028
* LIST: pvalue containing a list
1029
*================================*/
1031
pvalue_to_list (PVALUE val)
1033
return (LIST)pvalue(val);
1069
return (NODE)pvalvv(val);
1035
1071
/*==================================
1036
1072
* record pvalues (PINDI, PFAM, ...)
1037
1073
*================================*/
1075
pvalue_to_record (PVALUE val)
1077
RECORD rec = pvalvv(val); /* may be NULL */
1078
ASSERT(is_record_pvalue(val));
1039
1082
pvalue_to_cel (PVALUE val)
1041
/* also load record into direct cache */
1042
CACHEEL cel = pvalue(val); /* may be NULL */
1043
ASSERT(is_record_pvalue(val));
1044
load_cacheel(cel); /* handles null cel ok */
1084
RECORD rec = pvalue_to_record(val);
1085
NODE root = nztop(rec); /* force record into cache */
1086
CACHEEL cel = nzcel(rec);
1087
root = root; /* NOTUSED */
1048
pvalue_to_rec (PVALUE val)
1050
CACHEEL cel = pvalue_to_cel(val);
1051
if (!cel) return NULL;
1052
return crecord(cel);
1090
/*==================================
1091
* LIST: pvalue containing a list
1092
*================================*/
1094
create_pvalue_from_list (LIST list)
1096
return create_pvalue(PLIST, list);
1099
pvalue_to_list (PVALUE val)
1101
return (LIST)pvalvv(val);
1103
/*==================================
1104
* TABLE: pvalue containing a table
1105
*================================*/
1107
create_pvalue_from_table (TABLE tab)
1109
return create_pvalue(PTABLE, tab);
1112
pvalue_to_table (PVALUE val)
1114
return (TABLE)pvalvv(val);
1054
1116
/*==================================
1055
1117
* PSET: pvalue containing a set (INDISEQ)
1056
1118
*================================*/
1058
create_pvalue_from_set (INDISEQ seq)
1120
create_pvalue_from_seq (INDISEQ seq)
1060
1122
return create_pvalue(PSET, seq);
1125
set_pvalue_seq (PVALUE val, INDISEQ seq)
1127
set_pvalue(val, PSET, (VPTR)seq);
1063
1130
pvalue_to_seq (PVALUE val)
1065
return (INDISEQ)pvalue(val);
1132
return (INDISEQ)pvalvv(val);
1067
1134
/*==================================
1068
* PSTRING: pvalue containing a string
1135
* ARRAY: pvalue containing an array
1069
1136
*================================*/
1071
create_pvalue_from_string (CNSTRING str)
1073
return create_pvalue(PSTRING, (VPTR)str);
1076
set_pvalue_string (PVALUE val, CNSTRING str)
1078
set_pvalue(val, PSTRING, (VPTR)str); /* makes new copy of string */
1081
pvalue_to_string (PVALUE val)
1083
return (STRING)pvalue(val);
1086
pvalue_to_table (PVALUE val)
1088
return (TABLE)pvalue(val);
1138
pvalue_to_array (PVALUE val)
1140
return (ARRAY)pvalvv(val);
1090
1142
/*========================================
1091
1143
* init_pvalue_vtable -- set vtable (for allocator in pvalalloc.c)
1144
1196
return 0; /* TODO: what about other types ? */
1198
/*=============================================
1199
* create_new_pvalue_table -- Create new table inside new pvalue
1200
*============================================*/
1202
create_new_pvalue_table (void)
1204
TABLE tab = create_table_custom_vptr(delete_vptr_pvalue);
1205
PVALUE val = create_pvalue_from_table(tab);
1209
/*=============================================
1210
* create_new_pvalue_list -- Create new list inside new pvalue
1211
*============================================*/
1213
create_new_pvalue_list (void)
1215
LIST list = create_list3(delete_vptr_pvalue);
1216
PVALUE val = create_pvalue_from_list(list);
1217
release_list(list); /* release our ref to list */
1220
/*=============================================
1221
* set_pvalue_to_pvalue -- Set val to be same value as src
1222
*============================================*/
1224
set_pvalue_to_pvalue (PVALUE val, const PVALUE src)
1226
set_pvalue(val, ptype(src), pvalvv(src));