Codebase list libmawk / bullseye-backports/main src / example_apps / 90_custom_array / carr.c

Tree @bullseye-backports/main (Download .tar.gz)

carr.c @bullseye-backports/mainraw · history · blame

#include "carr.h"

/* this example code demonstrates how to implement a virtual array that
   manipulates a C array. The code aims for simplicity so there's no
   locking of the C array, which is obviously common for any mawk instance:
   the code assumes a single thread.

   Index is integer between 0 and CARR_SIZE-1. Delete only sets value to 0.
   The iterator always goes between 0 and CARR_SIZE-1.


char carr[CARR_SIZE];

/* lookup: copy a cell of a member if res != NULL; if create_flag is non-zero,
   the index should be created. If result is non-NULL, it must be destroyed.
   Result can be the same as cidx!
    -1 on error
     0 if index does not exist
     1 if it does exist
   Because we have a static array, we won't ever return 0; also ignore the
   create flag. Return -1 for boundary error.
int carr_find(mawk_state_t *MAWK, mawk_array_t A, const mawk_cell_t *cidx, mawk_cell_t *res, int create_flag)
	int idx;
	idx = libmawk_cell2int(MAWK, cidx);
	if ((idx < 0) || (idx >= CARR_SIZE))
		return -1;
	if (res != NULL) {
		mawk_cell_destroy(MAWK, res);
		res->type = C_NUM;
		res->d.dval = carr[idx];
	return 1;

/* set the value of an element of the array. The val cell may have any type! */
void carr_set(mawk_state_t *MAWK, mawk_array_t A, const mawk_cell_t *cidx, mawk_cell_t *val)
	int idx;
	char cval;

	idx = libmawk_cell2int(MAWK, cidx);
	if ((idx < 0) || (idx >= CARR_SIZE))
	switch(val->type) {
		case C_NUM:
		case C_STRNUM:
		case C_MBSTRN:
			carr[idx] = libmawk_cell2int(MAWK, val);
		case C_STRING:
				char buff[2];
				libmawk_print_cell(MAWK, val, buff, 2);
				carr[idx] = buff[0];
			carr[idx] = 0;

/* delete a cell (since our array is static, set the value to 0) */
static void carr_delete(mawk_state_t *MAWK, mawk_array_t A, const mawk_cell_t *idx)
	mawk_cell_t zero;
	zero.type = C_NUM;
	zero.d.dval = 0;
	carr_set(MAWK, A, idx, &zero);

/* set up an iterator; the iterator state is just an integer index */
typedef struct {
	int idx;
	mawk_cell_t cidx;
} carr_it_t;

void *carr_it_start(mawk_state_t *MAWK, mawk_array_t A)
	carr_it_t *i;
	i = malloc(sizeof(carr_it_t));
	i->idx = -1;
	i->cidx.type = C_NUM;
	return i;

/* return next element using an iterator (thread safe) */
const mawk_cell_t *carr_it_next(mawk_state_t *MAWK, mawk_array_t A, void *iterator)
	carr_it_t *i = iterator;
	if (i->idx >= CARR_SIZE)
		return NULL;
	i->cidx.d.dval = i->idx;
	return &i->cidx;

/* finish iteration */
void carr_it_stop(mawk_state_t *MAWK, mawk_array_t A, void *iterator)
	/* no need to destroy iterator->cidx as it was a number all the time */

/* NOTE: the above code tries to be readable, thus there's a separate
   integer index an a cell for sotring the return-cell are in the iterator.
   The code could be shorter taking less ram if the iterator was a cell
   whose (int)d.dval stored the index. */

/* the implementation struct that describes how the array is implemented */
array_imp_t carr_imp = {
	/* low level access: find an index, set and delete members */

	/* use the generic implementation for high level calls, because... */

	/* ... the low level iterator is implemented: */

/* set up the array as a built-in */
void custom_array_init(mawk_state_t *m)
	/* register the new array */
	libmawk_register_array(m, "CARR", &carr_imp);

	/* globals should be zero'd, but to make it absolutely clear: */
	memset(carr, 0, sizeof(carr));