3bf951f42c
Files correlati : pdflib Ricompilazione Demo : [ ] Commento : Aggiornata pdflib.dll alla versione 7.0.4 git-svn-id: svn://10.65.10.50/trunk@18580 c028cbd2-c16b-5b4b-a496-9718f37d4682
519 lines
11 KiB
C
Executable File
519 lines
11 KiB
C
Executable File
/*---------------------------------------------------------------------------*
|
|
| PDFlib - A library for generating PDF on the fly |
|
|
+---------------------------------------------------------------------------+
|
|
| Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
|
|
+---------------------------------------------------------------------------+
|
|
| |
|
|
| This software is subject to the PDFlib license. It is NOT in the |
|
|
| public domain. Extended versions and commercial licenses are |
|
|
| available, please check http://www.pdflib.com. |
|
|
| |
|
|
*---------------------------------------------------------------------------*/
|
|
|
|
/* $Id: pc_contain.c,v 1.3 2009-03-23 08:51:17 guy Exp $
|
|
*
|
|
* PDFlib generic container classes
|
|
*
|
|
*/
|
|
|
|
#include "pc_util.h"
|
|
#include "pc_contain.h"
|
|
|
|
|
|
/**************************** avl tree class ****************************/
|
|
|
|
typedef struct avl_node_s avl_node;
|
|
|
|
struct avl_node_s
|
|
{
|
|
const char *name;
|
|
int balance;
|
|
avl_node * left;
|
|
avl_node * right;
|
|
};
|
|
|
|
#undef COMMENT
|
|
#ifdef COMMENT
|
|
|
|
before single rotate right; after insertion of X.
|
|
|
|
root(-2)
|
|
|
|
/ \
|
|
|
|
lc(-1) +------+
|
|
| rc |
|
|
/ \ | |
|
|
| |
|
|
+------+ +------+ | |
|
|
| llc | | rlc | | n |
|
|
| | | | +------+
|
|
| | | |
|
|
| | | |
|
|
| n | | n |
|
|
+------+ +------+
|
|
|
|
|
|
|
|
|
X
|
|
|
|
|
|
after single rotate right.
|
|
|
|
lc(0)
|
|
|
|
/ \
|
|
|
|
+------+ root(0)
|
|
| llc |
|
|
| | / \
|
|
| |
|
|
| | +------+ +------+
|
|
| n | | rlc | | rc |
|
|
+------+ | | | |
|
|
| | | |
|
|
| | | | |
|
|
| n | | n |
|
|
X +------+ +------+
|
|
|
|
|
|
|
|
before double rotate right; after insertion of X/Y.
|
|
|
|
root(-2)
|
|
|
|
/ \
|
|
|
|
lc(+1) +------+
|
|
| rc |
|
|
/ \ | |
|
|
| |
|
|
+------+ rlc(-1/+1) | |
|
|
| llc | | |
|
|
| | / \ | |
|
|
| | | |
|
|
| | +------+ +------+ | n |
|
|
| | | lrlc | | rrlc | +------+
|
|
| | | | | |
|
|
| | | | | |
|
|
| n | | n-1 | | n-1 |
|
|
+------+ +------+ +------+
|
|
|
|
| |
|
|
|
|
X Y
|
|
|
|
|
|
after double rotate right:
|
|
|
|
rlc(0)
|
|
|
|
/ \
|
|
|
|
lc(0/-1) root(+1/0)
|
|
|
|
/ \ / \
|
|
|
|
+------+ +------+ +------+ +------+
|
|
| llc | | lrlc | | rrlc | | rc |
|
|
| | | | | | | |
|
|
| | | | | | | |
|
|
| | | n-1 | | n-1 | | |
|
|
| | +------+ +------+ | |
|
|
| | | |
|
|
| | | | | |
|
|
| n | | n |
|
|
+------+ X Y +------+
|
|
|
|
|
|
avl_node *
|
|
avl_insert(avl_node *root, const char *name, pdc_bool *change_parent_balance)
|
|
{
|
|
pdc_bool change_balance = pdc_false;
|
|
|
|
if (root == 0)
|
|
{
|
|
avl_node *result = (avl_node *) malloc(sizeof (avl_node));
|
|
|
|
result->name = name;
|
|
result->balance = 0;
|
|
result->left = (avl_node *) 0;
|
|
result->right = (avl_node *) 0;
|
|
*change_parent_balance = pdc_true;
|
|
return result;
|
|
}
|
|
|
|
if (strcmp(name, root->name) < 0)
|
|
{
|
|
root->left = avl_insert(root->left, name, &change_balance);
|
|
|
|
if (change_balance && --root->balance < 0)
|
|
{
|
|
if (root->balance == -1)
|
|
{
|
|
*change_parent_balance = pdc_true;
|
|
}
|
|
else /* root->balance == -2 */
|
|
{
|
|
avl_node *lc = root->left; /* left child */
|
|
avl_node *rlc = lc->right; /* right of left child */
|
|
|
|
if (lc->balance == -1) /* single rotate right */
|
|
{
|
|
root->left = rlc;
|
|
lc->right = root;
|
|
lc->balance = root->balance = 0;
|
|
return lc;
|
|
}
|
|
else /* double rotate right */
|
|
{
|
|
root->balance = (rlc->balance == -1) ? +1 : 0;
|
|
lc->balance = (rlc->balance == +1) ? -1 : 0;
|
|
rlc->balance = 0;
|
|
lc->right = rlc->left;
|
|
rlc->left = lc;
|
|
root->left = rlc->right;
|
|
rlc->right = root;
|
|
return rlc;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
root->right = avl_insert(root->right, name, &change_balance);
|
|
|
|
if (change_balance && ++root->balance > 0)
|
|
{
|
|
if (root->balance == +1)
|
|
{
|
|
*change_parent_balance = pdc_true;
|
|
}
|
|
else /* root->balance == +2 */
|
|
{
|
|
avl_node *rc = root->right; /* right child */
|
|
avl_node *lrc = rc->left; /* left of right child */
|
|
|
|
if (rc->balance == +1) /* single rotate left */
|
|
{
|
|
root->right = lrc;
|
|
rc->left = root;
|
|
rc->balance = root->balance = 0;
|
|
return rc;
|
|
}
|
|
else /* double rotate left */
|
|
{
|
|
root->balance = (lrc->balance == +1) ? -1 : 0;
|
|
rc->balance = (lrc->balance == -1) ? +1 : 0;
|
|
lrc->balance = 0;
|
|
rc->left = lrc->right;
|
|
lrc->right = rc;
|
|
root->right = lrc->left;
|
|
lrc->left = root;
|
|
return lrc;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return root;
|
|
}
|
|
|
|
#endif /* COMMENT */
|
|
|
|
/***************************** vector class *****************************/
|
|
|
|
struct pdc_vtr_s
|
|
{
|
|
pdc_core * pdc;
|
|
|
|
pdc_ced ced; /* container entry descriptor */
|
|
void * context; /* client context */
|
|
|
|
char ** ctab; /* chunk table */
|
|
int ctab_size; /* current # of slots */
|
|
int ctab_incr;
|
|
int chunk_size; /* # of items per chunk */
|
|
int size; /* current # of items total */
|
|
};
|
|
|
|
|
|
static const pdc_vtr_parms vtr_dflt_parms =
|
|
{
|
|
0, /* init_size */
|
|
100, /* chunk_size */
|
|
10 /* ctab_incr */
|
|
};
|
|
|
|
void
|
|
pdc_vtr_dflt_parms(pdc_vtr_parms *vp)
|
|
{
|
|
*vp = vtr_dflt_parms;
|
|
}
|
|
|
|
|
|
static void
|
|
pdc_vtr_grow_ctab(pdc_vtr *v, int new_size)
|
|
{
|
|
static const char fn[] = "pdc_vtr_grow_ctab";
|
|
|
|
int i;
|
|
|
|
v->ctab = (char **)
|
|
pdc_realloc(v->pdc, v->ctab, (size_t) (new_size * sizeof (char *)), fn);
|
|
|
|
for (i = v->ctab_size; i < new_size; ++i)
|
|
v->ctab[i] = (char *) 0;
|
|
|
|
v->ctab_size = new_size;
|
|
} /* pdc_vtr_grow_ctab */
|
|
|
|
|
|
pdc_vtr *
|
|
pdc_vtr_new(
|
|
pdc_core *pdc,
|
|
const pdc_ced *ced,
|
|
void *context,
|
|
const pdc_vtr_parms *parms)
|
|
{
|
|
static const char fn[] = "pdc_vtr_new";
|
|
|
|
pdc_vtr *v = (pdc_vtr *) pdc_malloc(pdc, sizeof (pdc_vtr), fn);
|
|
|
|
if (!parms)
|
|
parms = &vtr_dflt_parms;
|
|
|
|
v->pdc = pdc;
|
|
v->ced = *ced;
|
|
v->context = context ? context : pdc;
|
|
|
|
v->ctab = (char **) 0;
|
|
v->ctab_size = 0;
|
|
v->ctab_incr = parms->ctab_incr;
|
|
v->chunk_size = parms->chunk_size;
|
|
v->size = 0;
|
|
|
|
if (parms->init_size != 0)
|
|
{
|
|
PDC_TRY (pdc)
|
|
{
|
|
pdc_vtr_resize(v, parms->init_size);
|
|
}
|
|
PDC_CATCH (pdc)
|
|
{
|
|
pdc_vtr_delete(v);
|
|
PDC_RETHROW(pdc);
|
|
}
|
|
}
|
|
|
|
return v;
|
|
} /* pdc_vtr_new */
|
|
|
|
|
|
void
|
|
pdc_vtr_delete(pdc_vtr *v)
|
|
{
|
|
int cs = v->chunk_size;
|
|
int i;
|
|
|
|
if (v->size != 0 && v->ced.release)
|
|
{
|
|
for (i = 0; i < v->size; ++i)
|
|
{
|
|
v->ced.release(v->context, (void *)
|
|
&v->ctab[i / cs][(i % cs) * v->ced.size]);
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < v->ctab_size && v->ctab[i] != (char *) 0; ++i)
|
|
{
|
|
pdc_free(v->pdc, v->ctab[i]);
|
|
}
|
|
|
|
if (v->ctab)
|
|
pdc_free(v->pdc, v->ctab);
|
|
|
|
pdc_free(v->pdc, v);
|
|
} /* pdc_vtr_delete */
|
|
|
|
|
|
int
|
|
pdc_vtr_size(const pdc_vtr *v)
|
|
{
|
|
return (int) v->size;
|
|
} /* pdc_vtr_size */
|
|
|
|
|
|
void
|
|
pdc_vtr_resize(pdc_vtr *v, int new_size)
|
|
{
|
|
static const char fn[] = "pdc_vtr_resize";
|
|
|
|
int cs = v->chunk_size;
|
|
|
|
PDC_ASSERT(v->pdc, 0 <= new_size);
|
|
|
|
if (new_size < v->size)
|
|
{
|
|
if (!v->ced.release)
|
|
{
|
|
v->size = new_size;
|
|
}
|
|
else
|
|
{
|
|
do
|
|
{
|
|
--v->size;
|
|
|
|
v->ced.release(v->context, (void *)
|
|
&v->ctab[v->size / cs][(v->size % cs) * v->ced.size]);
|
|
} while (new_size < v->size);
|
|
}
|
|
|
|
/* TODO: free chunks if possible? */
|
|
}
|
|
else if (new_size > v->size)
|
|
{
|
|
int curr_slot = v->size / cs;
|
|
int new_ctsize = (new_size + cs - 1) / cs;
|
|
int i;
|
|
|
|
if (v->ctab_size < new_ctsize)
|
|
pdc_vtr_grow_ctab(v, new_ctsize);
|
|
|
|
for (i = curr_slot; i < new_ctsize; ++i)
|
|
{
|
|
if (v->ctab[i] == (char *) 0)
|
|
{
|
|
v->ctab[i] = (char *)
|
|
pdc_malloc(v->pdc, (size_t) (cs * v->ced.size), fn);
|
|
}
|
|
}
|
|
|
|
if (v->ced.reclaim)
|
|
{
|
|
for (i = v->size; i < new_size; ++i)
|
|
{
|
|
v->ced.reclaim((void *) &v->ctab[i/cs][(i%cs) * v->ced.size]);
|
|
}
|
|
}
|
|
|
|
v->size = new_size;
|
|
}
|
|
} /* pdc_vtr_resize */
|
|
|
|
|
|
void *
|
|
pdc__vtr_at(const pdc_vtr *v, int idx)
|
|
{
|
|
static const char fn[] = "pdc__vtr_at";
|
|
|
|
int cs = v->chunk_size;
|
|
|
|
if (idx < 0 || v->size <= idx)
|
|
pdc_error(v->pdc, PDC_E_INT_ARRIDX,
|
|
pdc_errprintf(v->pdc, "%d", idx), fn, 0, 0);
|
|
/* TODO: "%u" */
|
|
|
|
return (void *) (&v->ctab[idx / cs][(idx % cs) * v->ced.size]);
|
|
} /* pdc__vtr_at */
|
|
|
|
|
|
#if 0
|
|
const void *
|
|
pdc__vtr_at_c(const pdc_vtr *v, int idx)
|
|
{
|
|
static const char fn[] = "pdc__vtr_at_c";
|
|
|
|
int cs = v->chunk_size;
|
|
|
|
if (idx < 0 || v->size <= idx)
|
|
pdc_error(v->pdc, PDC_E_INT_ARRIDX,
|
|
pdc_errprintf(v->pdc, "%d", idx), fn, 0, 0);
|
|
/* TODO: "%u" */
|
|
|
|
return (const void *) (&v->ctab[idx / cs][(idx % cs) * v->ced.size]);
|
|
} /* pdc__vtr_at_c */
|
|
#endif
|
|
|
|
|
|
void *
|
|
pdc__vtr_top(const pdc_vtr *v)
|
|
{
|
|
int cs = v->chunk_size;
|
|
int idx;
|
|
|
|
if (v->size == 0)
|
|
return (void *) 0;
|
|
|
|
idx = v->size - 1;
|
|
return (void *) (&v->ctab[idx / cs][(idx % cs) * v->ced.size]);
|
|
} /* pdc__vtr_top */
|
|
|
|
|
|
#if 0
|
|
const void *
|
|
pdc__vtr_top_c(const pdc_vtr *v)
|
|
{
|
|
int cs = v->chunk_size;
|
|
int idx;
|
|
|
|
if (v->size == 0)
|
|
return (void *) 0;
|
|
|
|
idx = v->size - 1;
|
|
return (const void *) (&v->ctab[idx / cs][(idx % cs) * v->ced.size]);
|
|
} /* pdc__vtr_top_c */
|
|
#endif
|
|
|
|
|
|
void *
|
|
pdc__vtr_push(pdc_vtr *v)
|
|
{
|
|
static char fn[] = "pdc__vtr_push";
|
|
|
|
int cs = v->chunk_size;
|
|
int idx = v->size;
|
|
int slot = idx / cs;
|
|
char *target;
|
|
|
|
if (v->ctab_size <= slot)
|
|
pdc_vtr_grow_ctab(v, v->ctab_size + v->ctab_incr);
|
|
|
|
if (v->ctab[slot] == (char *) 0)
|
|
{
|
|
v->ctab[slot] = (char *)
|
|
pdc_malloc(v->pdc, (size_t) (cs * v->ced.size), fn);
|
|
}
|
|
|
|
++v->size;
|
|
target = &v->ctab[slot][(idx % cs) * v->ced.size];
|
|
|
|
if (v->ced.reclaim)
|
|
{
|
|
v->ced.reclaim((void *) target);
|
|
}
|
|
|
|
return (void *) target;
|
|
} /* pdc__vtr_push */
|
|
|
|
|
|
void
|
|
pdc_vtr_pop(pdc_vtr *v)
|
|
{
|
|
static char fn[] = "pdc_vtr_pop";
|
|
|
|
int cs = v->chunk_size;
|
|
|
|
if (v->size == 0)
|
|
pdc_error(v->pdc, PDC_E_INT_STACK_UNDER, fn, 0, 0, 0);
|
|
|
|
--v->size;
|
|
|
|
if (v->ced.release)
|
|
{
|
|
v->ced.release(v->context, (void *)
|
|
&v->ctab[v->size / cs][(v->size % cs) * v->ced.size]);
|
|
}
|
|
} /* pdc_vtr_pop */
|