Files
calc/size.c
Landon Curt Noll db77e29a23 convert ASCII TABs to ASCII SPACEs
Converted all ASCII tabs to ASCII spaces using a 8 character
tab stop, for all files, except for all Makefiles (plus rpm.mk).
The `git diff -w` reports no changes.
2024-07-11 22:03:52 -07:00

445 lines
13 KiB
C

/*
* size - size and sizeof functions are implemented here
*
* Copyright (C) 1999-2007,2021-2023 David I. Bell
*
* Calc is open software; you can redistribute it and/or modify it under
* the terms of the version 2.1 of the GNU Lesser General Public License
* as published by the Free Software Foundation.
*
* Calc is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
* Public License for more details.
*
* A copy of version 2.1 of the GNU Lesser General Public License is
* distributed with calc under the filename COPYING-LGPL. You should have
* received a copy with calc; if not, write to Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Under source code control: 1997/03/10 01:56:51
* File existed as early as: 1997
*
* Share and enjoy! :-) http://www.isthe.com/chongo/tech/comp/calc/
*/
#include "value.h"
#include "zrand.h"
#include "zrandom.h"
#include "block.h"
#include "errtbl.h"
#include "banned.h" /* include after system header <> includes */
/*
* forward declarations
*/
S_FUNC size_t zsize(ZVALUE);
S_FUNC size_t qsize(NUMBER*);
S_FUNC size_t csize(COMPLEX*);
S_FUNC size_t memzsize(ZVALUE);
S_FUNC size_t memqsize(NUMBER*);
/*
* elm_count - return information about the number of elements
*
* Return information about the number of elements or part of
* a value. This is what the size() builtin returns with the
* exception of the V_FILE type. To get V_FILE size length,
* the getsize(vp->v_file, &len) should be called directly.
*
* This is not the sizeof, see lsizeof() for that information.
*
* given:
* vp pointer to a value
*
* return:
* number of elements
*/
long
elm_count(VALUE *vp)
{
long result;
/*
* return information about the number of elements
*
* This is not the sizeof, see lsizeof() for that information.
* This is does not include overhead, see memsize() for that info.
*/
switch (vp->v_type) {
case V_NULL:
case V_INT:
case V_ADDR:
case V_OCTET:
result = 0;
break;
case V_MAT:
result = vp->v_mat->m_size;
break;
case V_LIST:
result = vp->v_list->l_count;
break;
case V_ASSOC:
result = vp->v_assoc->a_count;
break;
case V_OBJ:
result = vp->v_obj->o_actions->oa_count;
break;
case V_STR:
result = vp->v_str->s_len;
break;
case V_BLOCK:
result = (long) vp->v_block->datalen;
break;
case V_NBLOCK:
result = (long) vp->v_nblock->blk->datalen;
break;
/*
* V_NUM, V_COM, V_RAND, V_RANDOM, V_CONFIG, V_HASH
*
* V_FILE (use getsize(vp->v_file, &len) for file length)
*/
default:
result = (vp->v_type > 0);
break;
}
return result;
}
/*
* zsize - calculate memory footprint of a ZVALUE (excluding overhead)
*
* The numeric -1, - and 1 storage values are ignored.
*
* given:
* z ZVALUE to examine
*
* returns:
* value size
*/
S_FUNC size_t
zsize(ZVALUE z)
{
/* ignore the size of 0, 1 and -1 */
if (z.v != _zeroval_ && z.v != _oneval_ && !zisunit(z) && !ziszero(z)) {
return z.len * sizeof(HALF);
} else {
return (size_t)0;
}
}
/*
* qsize - calculate memory footprint of a NUMBER (excluding overhead)
*
* The numeric -1, - and 1 storage values are ignored. Denominator
* parts of integers are ignored.
*
* given:
* q pointer to NUMBER to examine
*
* returns:
* value size
*/
S_FUNC size_t
qsize(NUMBER *q)
{
/* ignore denominator parts of integers */
if (qisint(q)) {
return zsize(q->num);
} else {
return (zsize(q->num) + zsize(q->den));
}
}
/*
* csize - calculate memory footprint of a COMPLEX (excluding overhead)
*
* The numeric -1, - and 1 storage values are ignored. Denominator
* parts of integers are ignored. Imaginary parts of pure reals
* are ignored.
*
* given:
* c pointer to COMPLEX to examine
*
* returns:
* value size
*/
S_FUNC size_t
csize(COMPLEX *c)
{
/* ignore denominator parts of integers */
if (cisreal(c)) {
return qsize(c->real);
} else {
return (qsize(c->real) + qsize(c->imag));
}
}
/*
* memzsize - calculate memory footprint of a ZVALUE including overhead
*
* given:
* z ZVALUE to examine
*
* returns:
* memory footprint
*/
S_FUNC size_t
memzsize(ZVALUE z)
{
return sizeof(ZVALUE) + (z.len * sizeof(HALF));
}
/*
* memqsize - calculate memory footprint of a NUMBER including overhead
*
* given:
* q pointer of NUMBER to examine
*
* returns:
* memory footprint
*/
S_FUNC size_t
memqsize(NUMBER *q)
{
return sizeof(NUMBER) + memzsize(q->num) + memzsize(q->den);
}
/*
* lsizeof - calculate memory footprint of a VALUE (not counting overhead)
*
* given:
* vp pointer of VALUE to examine
*
* returns:
* memory footprint
*/
size_t
lsizeof(VALUE *vp)
{
VALUE *p;
LISTELEM *ep;
OBJECTACTIONS *oap;
ASSOCELEM *aep;
ASSOCELEM **ept;
size_t s;
long i;
/*
* return information about memory footprint
*
* This is not the number of elements, see elm_count() for that info.
* This is does not include overhead, see memsize() for that info.
*/
i = 0;
s = 0;
if (vp->v_type > 0) {
switch(vp->v_type) {
case V_INT:
case V_ADDR:
case V_OCTET:
break;
case V_NUM:
s = qsize(vp->v_num);
break;
case V_COM:
s = csize(vp->v_com);
break;
case V_STR:
s = vp->v_str->s_len + 1;
break;
case V_MAT:
i = vp->v_mat->m_size;
p = vp->v_mat->m_table;
while (i-- > 0)
s += lsizeof(p++);
break;
case V_LIST:
for (ep = vp->v_list->l_first; ep; ep = ep->e_next) {
s += lsizeof(&ep->e_value);
}
break;
case V_ASSOC:
i = vp->v_assoc->a_size;
ept = vp->v_assoc->a_table;
while (i-- > 0) {
for (aep = ept[i]; aep; aep = aep->e_next) {
s += lsizeof(&aep->e_value);
}
}
break;
case V_OBJ:
oap = vp->v_obj->o_actions;
i = oap->oa_count;
p = vp->v_obj->o_table;
while (i-- > 0)
s += lsizeof(p++);
break;
case V_FILE:
s = sizeof(vp->v_file);
break;
case V_RAND:
s = sizeof(RAND);
break;
case V_RANDOM:
s = sizeof(RANDOM) +
zsize(vp->v_random->n) +
zsize(vp->v_random->r);
break;
case V_CONFIG:
s = sizeof(CONFIG) +
strlen(vp->v_config->prompt1) +
strlen(vp->v_config->prompt2) + 2;
break;
case V_HASH:
/* ignore the unused part of the union */
s = sizeof(HASH) +
vp->v_hash->unionsize -
sizeof(vp->v_hash->h_union);
break;
case V_BLOCK:
s = vp->v_block->maxsize;
break;
case V_NBLOCK:
s = vp->v_nblock->blk->maxsize;
break;
default:
math_error("sizeof not defined for value type");
not_reached();
}
}
return s;
}
/*
* memsize - calculate memory footprint of a VALUE including overhead
*
* given:
* vp pointer of VALUE to examine
*
* returns:
* memory footprint including overhead
*/
size_t
memsize(VALUE *vp)
{
size_t s;
long i, j;
VALUE *p;
LISTELEM *ep;
OBJECTACTIONS *oap;
ASSOCELEM *aep;
ASSOCELEM **ept;
/*
* return information about memory footprint
*
* This is not the sizeof, see memsize() for that information.
* This is not the number of elements, see elm_count() for that info.
*/
i = j = 0;
s = sizeof(VALUE);
if (vp->v_type > 0) {
switch(vp->v_type) {
case V_INT:
case V_ADDR:
case V_OCTET:
break;
case V_NUM:
s = memqsize(vp->v_num);
break;
case V_COM:
s = sizeof(COMPLEX) +
memqsize(vp->v_com->real) +
memqsize(vp->v_com->imag);
break;
case V_STR:
s = sizeof(STRING) + vp->v_str->s_len + 1;
break;
case V_MAT:
s = sizeof(MATRIX);
i = vp->v_mat->m_size;
p = vp->v_mat->m_table;
while (i-- > 0)
s += memsize(p++);
break;
case V_LIST:
s = sizeof(LIST);
for (ep = vp->v_list->l_first; ep; ep = ep->e_next) {
s += sizeof(LISTELEM) - sizeof(VALUE) +
memsize(&ep->e_value);
}
break;
case V_ASSOC:
s = sizeof(ASSOC);
i = vp->v_assoc->a_size;
ept = vp->v_assoc->a_table;
while (i-- > 0) {
s += sizeof(ASSOCELEM *);
for (aep = *ept++; aep; aep = aep->e_next) {
s += sizeof(ASSOCELEM) - sizeof(VALUE) +
memsize(&aep->e_value);
j = aep->e_dim;
p = aep->e_indices;
while (j-- > 0)
s += memsize(p++);
}
}
break;
case V_OBJ:
s = sizeof(OBJECT);
oap = vp->v_obj->o_actions;
i = oap->oa_count;
s += (i + 3) * sizeof(int);
p = vp->v_obj->o_table;
while (i-- > 0)
s += memsize(p++);
break;
case V_FILE:
s = sizeof(vp->v_file);
break;
case V_RAND:
s = sizeof(RAND);
break;
case V_RANDOM:
s = sizeof(RANDOM) +
memzsize(vp->v_random->n) +
memzsize(vp->v_random->r);
break;
case V_CONFIG:
s = sizeof(CONFIG) + 2 +
strlen(vp->v_config->prompt1) +
strlen(vp->v_config->prompt2);
break;
case V_HASH:
s = sizeof(HASH);
break;
case V_BLOCK:
s = sizeof(BLOCK) + vp->v_block->maxsize;
break;
case V_NBLOCK:
s = sizeof(NBLOCK) + sizeof(BLOCK) +
vp->v_nblock->blk->maxsize +
strlen(vp->v_nblock->name) + 1;
break;
default:
math_error("memsize not defined for value type");
not_reached();
}
}
return s;
}