File: dbm_kaztree.c

package info (click to toggle)
freecell-solver 5.0.0-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 4,256 kB
  • sloc: ansic: 28,700; perl: 10,050; xml: 5,600; python: 1,339; sh: 533; cpp: 275; makefile: 20; javascript: 8
file content (147 lines) | stat: -rw-r--r-- 4,060 bytes parent folder | download | duplicates (3)
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
/*
 * This file is part of Freecell Solver. It is subject to the license terms in
 * the COPYING.txt file found in the top-level directory of this distribution
 * and at http://fc-solve.shlomifish.org/docs/distro/COPYING.html . No part of
 * Freecell Solver, including this file, may be copied, modified, propagated,
 * or distributed except according to the terms contained in the COPYING file.
 *
 * Copyright (c) 2000 Shlomi Fish
 */
#include "dbm_solver.h"
#include "generic_tree.h"
#include "dbm_kaztree_compare.h"

typedef struct
{
    dict_t *kaz_tree;
    meta_allocator meta_alloc;
#ifndef FCS_LIBAVL_STORE_WHOLE_KEYS
    compact_allocator allocator;
#endif
} fcs_dbm;

void fc_solve_dbm_store_init(fcs_dbm_store *const store,
    const char *path GCC_UNUSED, void **const recycle_bin_ptr)
{
    fcs_dbm *const db = SMALLOC1(db);

    fc_solve_meta_compact_allocator_init(&(db->meta_alloc));

    db->kaz_tree = fc_solve_kaz_tree_create(
        compare_records, NULL, &(db->meta_alloc), recycle_bin_ptr);

#ifndef FCS_LIBAVL_STORE_WHOLE_KEYS
    fc_solve_compact_allocator_init(&(db->allocator), &(db->meta_alloc));
#endif

    *store = (fcs_dbm_store)db;
}

dict_t *__attribute__((pure)) fc_solve_dbm_store_get_dict(fcs_dbm_store store)
{
    return (((fcs_dbm *)store)->kaz_tree);
}

/*
 * Returns TRUE if the key was added (it didn't already exist.)
 * */
fcs_dbm_record *fc_solve_dbm_store_insert_key_value(fcs_dbm_store store,
    const fcs_encoded_state_buffer *key, fcs_dbm_record *const parent,
    const bool should_modify_parent GCC_UNUSED)
{
#ifdef FCS_LIBAVL_STORE_WHOLE_KEYS
    fcs_dbm_record record_on_stack;

    /* This memset() call is done to please valgrind and for general
     * good measure. It is not absolutely necessary (but should not
     * hurt much). It is needed due to struct padding and alignment
     * issues.
     * */
    memset(&record_on_stack, '\0', sizeof(record_on_stack));
#endif

    fcs_dbm *const db = (fcs_dbm *)store;

    fcs_dbm_record *to_check;
#ifdef FCS_LIBAVL_STORE_WHOLE_KEYS
    to_check = &record_on_stack;
#else
    to_check = (fcs_dbm_record *)fcs_compact_alloc_ptr(
        &(db->allocator), sizeof(*to_check));
#endif

#ifdef FCS_DBM_RECORD_POINTER_REPR
    to_check->key = *key;
    fcs_dbm_record_set_parent_ptr(to_check, parent);
#else
    to_check->key = *key;
    to_check->parent = parent->parent;
#endif
    bool ret = (fc_solve_kaz_tree_alloc_insert(db->kaz_tree, to_check) == NULL);

#ifndef FCS_LIBAVL_STORE_WHOLE_KEYS
    if (!ret)
    {
        fcs_compact_alloc_release(&(db->allocator));
    }
#endif
    if (ret)
    {
        if (should_modify_parent && parent)
        {
            fcs_dbm_record_increment_refcount(parent);
        }

        return ((fcs_dbm_record *)(fc_solve_kaz_tree_lookup_value(
            db->kaz_tree, to_check)));
    }
    else
    {
        return NULL;
    }
}

bool fc_solve_dbm_store_lookup_parent(
    fcs_dbm_store store, const unsigned char *key, unsigned char *parent)
{
    fcs_dbm_record to_check = {.key = *(const fcs_encoded_state_buffer *)key};

    dict_key_t existing =
        fc_solve_kaz_tree_lookup_value(((fcs_dbm *)store)->kaz_tree, &to_check);
    if (!existing)
    {
        return FALSE;
    }
    else
    {
#ifdef FCS_DBM_RECORD_POINTER_REPR
        fcs_dbm_record *const p =
            fcs_dbm_record_get_parent_ptr((fcs_dbm_record *)existing);

        if (p)
        {
            *(fcs_encoded_state_buffer *)parent = p->key;
        }
        else
        {
            fcs_init_encoded_state((fcs_encoded_state_buffer *)parent);
        }
#else
        *(fcs_encoded_state_buffer *)parent =
            ((fcs_dbm_record *)existing)->parent;
#endif
        return TRUE;
    }
}

extern void fc_solve_dbm_store_destroy(fcs_dbm_store store)
{
    fcs_dbm *const db = (fcs_dbm *)store;

    fc_solve_kaz_tree_destroy(db->kaz_tree);
#ifndef FCS_LIBAVL_STORE_WHOLE_KEYS
    fc_solve_compact_allocator_finish(&(db->allocator));
#endif
    fc_solve_meta_compact_allocator_finish(&(db->meta_alloc));
    free(db);
}