campo-sirio/pdf/pdcore/pc_contain.c
guy 3bf951f42c Patch level : 10.0
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
2009-03-23 08:55:58 +00:00

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 */