Beispiel #1
0
/*-------------------------------------------------------------------------*/
struct_t *
struct_new_anonymous (int num_members)

/* Create an empty anonymous struct instance with <num_members>
 * and return its pointer.
 * Return NULL when out of memory.
 *
 * The returned struct will have one reference.
 */

{
    struct_type_t * pType;
    struct_t      * pStruct;
    int             i;
    char            buf[100];
    Bool            gotError;

    (void) ref_mstring(STR_ANONYMOUS);
    (void) ref_mstring(STR_ANONYMOUS);
    pType = struct_new_type( STR_ANONYMOUS
                           , STR_ANONYMOUS
                           , 0
                           , NULL, num_members, NULL);
    if (pType == NULL)
        return NULL;

    pStruct = struct_new(pType);
    free_struct_type(pType);
      /* struct_new() added one ref, but since this is an anonymous
       * struct, the struct instance will hold the only ref.
       */

    if (pStruct == NULL)
    {
        // the type was not referenced by struct_new() in this case, so it must
        // not be freed.
        return NULL;
    }


    /* Create default members */
    gotError = MY_FALSE;
    for (i = 0; i < num_members; i++)
    {
        sprintf(buf, "m-%d", i);
        pType->member[i].name = new_tabled(buf);
        if (!pType->member[i].name)
        {
            debug_message("(%s:%d) Out of memory (%zu bytes) for member name\n"
                         , __FILE__, __LINE__, strlen(buf)
                         );
            gotError = MY_TRUE;
            break;
        }
        pType->member[i].type = lpctype_mixed;
    }

    if (gotError)
    {
        free_struct(pStruct);
        pStruct = NULL;
    }

    return pStruct;
} /* struct_new_anonymous() */
Beispiel #2
0
svalue_t *
f_psyc_parse (svalue_t *sp) {
    char *buffer = NULL;
    svalue_t *sv;
    vector_t *v, *list;
    mapping_t *map;
    char oper = 0;
    psycString name = {0,0}, value = {0,0}, elems[MAX_LIST_SIZE], elem;
    psycParseListState listState;
    int ret, retl, type = -1, error = 0;
    size_t size, i;
    ssize_t n;
    time_t timmy;

    if (!psyc_dispatch_callback)
      psyc_dispatch_callback = new_tabled("psyc_dispatch");

    if (!psyc_error_callback)
      psyc_error_callback = new_tabled("psyc_error");

    assert_shadow_sent(current_object);
    psyc_state_t *state = O_GET_PSYC_STATE(current_object);
    if (!state) {
	state = pxalloc(sizeof(psyc_state_t));
	if (!state) {
	    errorf("Out of memory for psyc state struct.\n");
	    return sp; // not reached
	}
	O_GET_PSYC_STATE(current_object) = state;
	memset(state, 0, sizeof(psyc_state_t));

	state->parser = pxalloc(sizeof(psycParseState));
	if (!state->parser) {
	    errorf("Out of memory for psyc parse state struct.\n");
	    return sp; // not reached
	}
	psyc_initParseState(state->parser);
    }
    v = state->packet;

    if (sp->type == T_POINTER) {
	errorf("\npsyc_parse got %ld int* bytes... not supported yet\n",
	       VEC_SIZE(sp->u.vec));
	return sp; // not reached
    } else if (sp->type == T_STRING) {
#ifdef DEBUG
	printf("\npsyc_parse got a %ld bytes long string...\n", mstrsize(sp->u.str));
#endif
	if (state->remaining) {
	    // there are remaining bytes from the previous call to psyc_parse,
	    // copy them together with the newly arrived data
	    buffer = pxalloc(state->remaining_len + mstrsize(sp->u.str));
	    if (!buffer) {
		errorf("Out of memory for psyc_parse buffer.\n");
		return sp; // not reached
	    }
	    memcpy(buffer, state->remaining, state->remaining_len);
	    memcpy(buffer + state->remaining_len, get_txt(sp->u.str),
		   mstrsize(sp->u.str));
	    psyc_setParseBuffer2(state->parser, buffer,
				 state->remaining_len + mstrsize(sp->u.str));
	    pfree(state->remaining);
	    state->remaining = NULL;
	    state->remaining_len = 0;
	} else {
	    psyc_setParseBuffer2(state->parser, get_txt(sp->u.str),
				 mstrsize(sp->u.str));
	}
    } else {
	errorf("\npsyc_parse got type %d, not supported\n", sp->type);
	return sp; // not reached
    }

    do {
	ret = psyc_parse(state->parser, &oper, &name, &value);
#ifdef DEBUG
	printf("#%2d %c%.*s = %.*s\n", ret, oper ? oper : ' ',
	       (int)name.length, name.ptr, (int)value.length, value.ptr);
#endif
	if (!state->packet) {
	    state->packet = allocate_array(4);
	    if (!state->packet) {
		errorf("Out of memory for psyc_parse array.\n");
		return sp; // not reached
	    }
	    v = state->packet;

	    map = allocate_mapping(0, 2);	// empty mapping
	    if (!map) {
		errorf("Out of memory for psyc_parse routing header.\n");
		return sp; // not reached
	    }
	    put_mapping(&v->item[PACKET_ROUTING], map);
	    map = allocate_mapping(0, 2);	// empty mapping
	    if (!map) {
		errorf("Out of memory for psyc_parse entity header.\n");
		return sp; // not reached
	    }
	    put_mapping(&v->item[PACKET_ENTITY], map);
	}

	switch (ret) {
	    case PSYC_PARSE_ENTITY_START: case PSYC_PARSE_BODY_START:
		// save oper, name & value in state at the start of
		// incomplete entity or body
		state->oper = oper;
		state->name = mstring_alloc_string(name.length);
		memcpy(get_txt(state->name), name.ptr, name.length);
		if (!state->name) {
		    errorf("Out of memory for name.\n");
		    return sp; // not reached
		}

		// allocate memory for the total length of the value
		state->value_len = 0;
		state->value = mstring_alloc_string(psyc_getParseValueLength(state->parser));
		if (!state->value) {
		    errorf("Out of memory for value.\n");
		    return sp; // not reached
		}

		// fall thru
	    case PSYC_PARSE_ENTITY_CONT:  case PSYC_PARSE_BODY_CONT:
	    case PSYC_PARSE_ENTITY_END:   case PSYC_PARSE_BODY_END:
		// append value to tmp buffer in state
		memcpy(get_txt(state->value) + state->value_len, value.ptr, value.length);
		state->value_len += value.length;
	}

	if (ret == PSYC_PARSE_ENTITY_END || ret == PSYC_PARSE_BODY_END) {
	    // incomplete entity or body parsing done,
	    // set oper/name/value to the ones saved in state
	    oper = state->oper;
	    name.ptr = get_txt(state->name);
	    name.length = mstrsize(state->name);
	    value.ptr = get_txt(state->value);
	    value.length = mstrsize(state->value);
	}

	switch (ret) {
	    case PSYC_PARSE_ROUTING:
		sv = pxalloc(sizeof(svalue_t));

		// new_n_tabled fetches a reference of a probably existing
		// shared string
		put_string(sv, new_n_tabled(name.ptr, name.length));
		sv = get_map_lvalue(v->item[PACKET_ROUTING].u.map, sv);
		put_number(&sv[1], oper);
		// strings are capable of containing 0 so we can do this
		// for binary data too. let's use a tabled string even
		// for values of routing variables as they repeat a lot
		put_string(sv, new_n_tabled(value.ptr, value.length));
		break;

	    case PSYC_PARSE_ENTITY_START:
	    case PSYC_PARSE_ENTITY_CONT:
		break;

	    case PSYC_PARSE_ENTITY_END:
	    case PSYC_PARSE_ENTITY:
		sv = pxalloc(sizeof(svalue_t));

		if (ret == PSYC_PARSE_ENTITY)
		    put_string(sv, new_n_tabled(name.ptr, name.length));
		else // PSYC_PARSE_ENTITY_END
		    put_string(sv, make_tabled(state->name));

		sv = get_map_lvalue(v->item[PACKET_ENTITY].u.map, sv);
		put_number(&sv[1], oper);

		type = psyc_getVarType(&name);

		switch (type) {
		    case PSYC_TYPE_DATE: // number + PSYC_EPOCH
			if (psyc_parseDate(&value, &timmy))
			    put_number(sv, timmy);
			else
			    error = PSYC_PARSE_ERROR_DATE;
			break;
		    case PSYC_TYPE_TIME: // number
			if (psyc_parseTime(&value, &timmy))
			    put_number(sv, timmy);
			else
			    error = PSYC_PARSE_ERROR_TIME;
			break;
		    case PSYC_TYPE_AMOUNT: // number
			if (psyc_parseNumber(&value, &n))
			    put_number(sv, n);
			else
			    error = PSYC_PARSE_ERROR_AMOUNT;
			break;
		    case PSYC_TYPE_DEGREE: // first digit
			if (value.length && value.ptr[0] >= '0' && value.ptr[0] <= '9')
			    put_number(sv, value.ptr[0] - '0');
			else
			    error = PSYC_PARSE_ERROR_DEGREE;
			break;
		    case PSYC_TYPE_FLAG: // 0 or 1
			if (value.length && value.ptr[0] >= '0' && value.ptr[0] <= '1')
			    put_number(sv, value.ptr[0] - '0');
			else
			    error = PSYC_PARSE_ERROR_FLAG;
			break;
		    case PSYC_TYPE_LIST: // array
			size = 0;
			if (value.length) {
			    psyc_initParseListState(&listState);
			    psyc_setParseListBuffer(&listState, value);
			    elem = (psycString){0, 0};
			    do {
				retl = psyc_parseList(&listState, &elem);
				switch (retl) {
				    case PSYC_PARSE_LIST_END:
					retl = 0;
				    case PSYC_PARSE_LIST_ELEM:
					if (size >= MAX_LIST_SIZE) {
					    error = PSYC_PARSE_ERROR_LIST_TOO_LARGE;
					    break;
					}
					elems[size++] = elem;
					break;
				    default:
					error = PSYC_PARSE_ERROR_LIST;
				}
			    } while (retl > 0 && !error);
			}
			if (error) break;

			list = allocate_array(size);
			for (i = 0; i < size; i++)
			    put_string(&list->item[i], new_n_tabled(elems[i].ptr,
			                                            elems[i].length));

			put_array(sv, list);
			break;
		    default: // string
			if (ret == PSYC_PARSE_ENTITY)
			    // is it good to put entity variable values into the
			    // shared string table? probably yes.. but it's a guess
			    //t_string(sv, new_n_mstring(value.ptr, value.length));
			    put_string(sv, new_n_tabled(value.ptr, value.length));
			else // PSYC_PARSE_ENTITY_END
			    put_string(sv, state->value);
		}
		break;

	    case PSYC_PARSE_BODY_START:
	    case PSYC_PARSE_BODY_CONT:
		break;

	    case PSYC_PARSE_BODY_END:
		put_string(&v->item[PACKET_METHOD], make_tabled(state->name));
		put_string(&v->item[PACKET_BODY], state->value);
		break;

	    case PSYC_PARSE_BODY:
		// new_n_tabled gets the shared string for the method
		put_string(&v->item[PACKET_METHOD],
			   new_n_tabled(name.ptr, name.length));

		// allocate an untabled string for the packet body
		put_string(&v->item[PACKET_BODY],
			   new_n_mstring(value.ptr, value.length));
		break;

	    case PSYC_PARSE_COMPLETE:
		put_array(inter_sp, v);
		sapply(psyc_dispatch_callback, current_object, 1);
		state->packet = NULL;
		break;

	    case PSYC_PARSE_INSUFFICIENT:
		// insufficient data, save remaining bytes
		state->remaining_len = psyc_getParseRemainingLength(state->parser);
		if (state->remaining_len) {
		    state->remaining = pxalloc(state->remaining_len);
		    memcpy(state->remaining,
			   psyc_getParseRemainingBuffer(state->parser),
			   state->remaining_len);
		} else
		    state->remaining = NULL;

		ret = 0;
		break;

	    default:
		error = ret;
	}

	switch (ret) {
	    case PSYC_PARSE_BODY_END:
	    case PSYC_PARSE_ENTITY_END:
		// reset tmp buffers in state when incomplete
		// entity or body parsing is finished
		state->oper = 0;
		state->name = NULL;
		state->value = NULL;
	}
    } while (ret && !error);

    if (buffer)
	pfree(buffer);

    free_svalue(sp);
    put_number(sp, error);
    return sp;
} /* f_psyc_parse */