:: # Copyright 2013, Big Switch Networks, Inc.
:: #
:: # LoxiGen is licensed under the Eclipse Public License, version 1.0 (EPL), with
:: # the following special exception:
:: #
:: # LOXI Exception
:: #
:: # As a special exception to the terms of the EPL, you may distribute libraries
:: # generated by LoxiGen (LoxiGen Libraries) under the terms of your choice, provided
:: # that copyright and licensing notices generated by LoxiGen are not altered or removed
:: # from the LoxiGen Libraries and the notice provided below is (i) included in
:: # the LoxiGen Libraries, if distributed in source code form and (ii) included in any
:: # documentation for the LoxiGen Libraries, if distributed in binary form.
:: #
:: # Notice: "Copyright 2013, Big Switch Networks, Inc. This library was generated by the LoxiGen Compiler."
:: #
:: # You may not use this file except in compliance with the EPL or LOXI Exception. You may obtain
:: # a copy of the EPL at:
:: #
:: # http://www.eclipse.org/legal/epl-v10.html
:: #
:: # Unless required by applicable law or agreed to in writing, software
:: # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
:: # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
:: # EPL for the specific language governing permissions and limitations
:: # under the EPL.
::
:: include('_copyright.c')

/****************************************************************
 *
 * of_object.c
 *
 * These are the low level object constructor/destructor operators.
 *
 ****************************************************************/

#include "loci_log.h"
#include <loci/loci.h>
#include <loci/loci_validator.h>

/**
 * Create a generic new object and possibly underlying wire buffer
 * @param bytes The number of bytes to allocate in the underlying buffer
 *
 * If bytes <= 0, do not allocate a wire buffer.
 *
 * Note that this is an internal function.  The class specific
 * new functions should be called to properly initialize and track an
 * OF object.
 */

of_object_t *
of_object_new(int bytes)
{
    of_object_t *obj;

    if ((obj = (of_object_t *)MALLOC(sizeof(*obj))) == NULL) {
        return NULL;
    }
    MEMSET(obj, 0, sizeof(*obj));

    if (bytes > 0) {
        if ((obj->wire_object.wbuf = of_wire_buffer_new(bytes)) == NULL) {
            FREE(obj);
            return NULL;
        }
        obj->wire_object.owned = 1;
    }

    return obj;
}

/**
 * The delete function for LOCI objects
 *
 * @param obj Pointer to the object to be deleted
 *
 * This can be called on any LOCI object; it should not need to be
 * overridden.
 */

void
of_object_delete(of_object_t *obj)
{
    if (obj == NULL) {
        return;
    }

    /*
     * Make callback if present
     */
    if (obj->track_info.delete_cb != NULL) {
        obj->track_info.delete_cb(obj);
    }

    if (obj->wire_object.owned) {
        of_wire_buffer_free(obj->wire_object.wbuf);
    }

    FREE(obj);
}

/**
 * Duplicate an object
 * @param src The object to be duplicated
 * @returns Pointer to the duplicate or NULL on error.  Caller is responsible
 * for freeing the returned object.
 */

of_object_t *
of_object_dup(of_object_t *src)
{
    of_object_t *dst;
    of_object_init_f init_fn;

    if ((dst = (of_object_t *)MALLOC(sizeof(*dst))) == NULL) {
        return NULL;
    }

    MEMSET(dst, 0, sizeof(*dst));

    /* Allocate a minimal wire buffer assuming we will not write to it. */
    if ((dst->wire_object.wbuf = of_wire_buffer_new(src->length)) == NULL) {
        FREE(dst);
        return NULL;
    }

    dst->wire_object.owned = 1;

    init_fn = of_object_init_map[src->object_id];
    init_fn(dst, src->version, src->length, 0);

    MEMCPY(OF_OBJECT_BUFFER_INDEX(dst, 0),
           OF_OBJECT_BUFFER_INDEX(src, 0),
           src->length);

    return dst;
}

/**
 * Generic new from message call
 */

of_object_t *
of_object_new_from_message(of_message_t msg, int len)
{
    of_object_id_t object_id;
    of_object_t *obj;
    of_version_t version;

    version = of_message_version_get(msg);
    if (!OF_VERSION_OKAY(version)) {
        return NULL;
    }

    if (of_validate_message(msg, len) != 0) {
        LOCI_LOG_ERROR("message validation failed\n");
        return NULL;
    }

    if ((obj = of_object_new(-1)) == NULL) {
        return NULL;
    }

    if (of_object_buffer_bind(obj, OF_MESSAGE_TO_BUFFER(msg), len, 
                              OF_MESSAGE_FREE_FUNCTION) < 0) {
        FREE(obj);
        return NULL;
    }
    obj->version = version;

    of_header_wire_object_id_get(obj, &object_id);
    of_object_init_map[object_id](obj, version, len, 0);

    return obj;
}

/**
 * Parse a message without allocating memory
 *
 * @param storage Pointer to an uninitialized of_object_storage_t
 * @param buf Pointer to the buffer
 * @param length Length of buf
 * @returns Pointer to an initialized of_object_t
 *
 * The lifetime of the returned object is the minimum of the lifetimes of
 * 'buf' and 'storage'.
 */

of_object_t *
of_object_new_from_message_preallocated(of_object_storage_t *storage,
                                        uint8_t *buf, int len)
{
    of_object_t *obj = &storage->obj;
    of_wire_buffer_t *wbuf = &storage->wbuf;
    of_message_t msg = buf;
    of_version_t version;
    of_object_id_t object_id;

    memset(storage, 0, sizeof(*storage));

    version = of_message_version_get(msg);
    if (!OF_VERSION_OKAY(version)) {
        return NULL;
    }

    if (of_validate_message(msg, len) != 0) {
        LOCI_LOG_ERROR("message validation failed\n");
        return NULL;
    }

    obj->version = version;
    obj->wire_object.wbuf = wbuf;
    wbuf->buf = msg;
    wbuf->alloc_bytes = len;
    wbuf->current_bytes = len;

    of_header_wire_object_id_get(obj, &object_id);
    of_object_init_map[object_id](obj, version, len, 0);

    return obj;
}

/**
 * Bind an existing buffer to an LOCI object
 *
 * @param obj Pointer to the object to be updated
 * @param buf Pointer to the buffer to bind to obj
 * @param bytes Length of buf
 * @param buf_free An optional free function to be applied to
 * buf on deallocation
 *
 * This can be called on any LOCI object; it should not need to be
 * overridden.
 */

int
of_object_buffer_bind(of_object_t *obj, uint8_t *buf, int bytes, 
                      of_buffer_free_f buf_free)
{
    of_wire_object_t *wobj;
    of_wire_buffer_t *wbuf;

    LOCI_ASSERT(buf != NULL);
    LOCI_ASSERT(bytes > 0);
    // LOCI_ASSERT(wobj is not bound);

    wobj = &obj->wire_object;
    MEMSET(wobj, 0, sizeof(*wobj));

    wbuf = of_wire_buffer_new_bind(buf, bytes, buf_free);
    if (wbuf == NULL) {
        return OF_ERROR_RESOURCE;
    }

    wobj->wbuf = wbuf;
    wobj->owned = 1;
    obj->length = bytes;

    return OF_ERROR_NONE;
}

/**
 * Connect a child to a parent at the wire buffer level
 *
 * @param parent The top level object to bind to
 * @param child The sub-object connecting to the parent
 * @param offset The offset at which to attach the child RELATIVE 
 * TO THE PARENT in the buffer
 * @param bytes The amount of the buffer dedicated to the child; see below
 * @param inc_ref_count Should the ref count of the parent be incremented
 * 
 * This is used for 'get' accessors for composite types as well as
 * iterator functions for lists, both read (first/next) and write
 * (append_init, append_advance).
 *
 * Connect a child object to a parent by setting up the child's
 * wire_object to point to the parent's underlying buffer.  The value
 * of the parameter bytes is important in determining how the child
 * is initialized:
 * @li If bytes <= 0, the length and type of the child are not modified;
 * no additional space is added to the buffer.
 * @li If bytes > 0, the current wire buffer is grown to 
 * accomodate this many bytes.  This is to support append operations.
 *
 * If an error is returned, future references to the child object
 * (until it is reinitialized) are undefined.
 */
static void
object_child_attach(of_object_t *parent, of_object_t *child, 
                       int offset, int bytes)
{
    of_wire_object_t *c_wobj; /* Pointer to child's wire object */
    of_wire_buffer_t *wbuf; /* Pointer to common wire buffer manager */

    child->parent = parent;
    wbuf = parent->wire_object.wbuf;

    /* Set up the child's wire buf to point to same as parent */
    c_wobj = &child->wire_object;
    c_wobj->wbuf = wbuf;
    c_wobj->obj_offset = parent->wire_object.obj_offset + offset;
    c_wobj->owned = 0;

    /*
     * bytes determines if this is a read or write setup.
     * If > 0, grow the buffer to accomodate the space
     * Otherwise do nothing
     */
    if (bytes > 0) { /* Set internal length, request buffer space */
        int tot_bytes; /* Total bytes to request for buffer if updated */

        /* Set up space for the child in the parent's buffer */
        tot_bytes = parent->wire_object.obj_offset + offset + bytes;

        of_wire_buffer_grow(wbuf, tot_bytes);
        child->length = bytes;
    }
    /* if bytes == 0 don't do anything */
}

/**
 * Check for room in an object's wire buffer.
 * @param obj The object being checked
 * @param new_len The desired length
 * @return Boolean
 */

int
of_object_can_grow(of_object_t *obj, int new_len)
{
    return OF_OBJECT_ABSOLUTE_OFFSET(obj, new_len) <=
        WBUF_ALLOC_BYTES(obj->wire_object.wbuf);
}

/**
 * Set the xid of a message object
 * @param obj The object being accessed
 * @param xid The xid value to store in the wire buffer
 * @return OF_ERROR_
 * Since the XID is common across all versions, this is used
 * for all XID accessors.
 */

int
of_object_xid_set(of_object_t *obj, uint32_t xid)
{
    of_wire_buffer_t *wbuf;

    if ((wbuf = OF_OBJECT_TO_WBUF(obj)) == NULL) {
        return OF_ERROR_PARAM;
    }
    of_wire_buffer_u32_set(wbuf, 
        OF_OBJECT_ABSOLUTE_OFFSET(obj, OF_MESSAGE_XID_OFFSET), xid);
    return OF_ERROR_NONE;
}

/**
 * Get the xid of a message object
 * @param obj The object being accessed
 * @param xid Pointer to where to store the xid value
 * @return OF_ERROR_
 * Since the XID is common across all versions, this is used
 * for all XID accessors.
 */

int
of_object_xid_get(of_object_t *obj, uint32_t *xid)
{
    of_wire_buffer_t *wbuf;

    if ((wbuf = OF_OBJECT_TO_WBUF(obj)) == NULL) {
        return OF_ERROR_PARAM;
    }
    of_wire_buffer_u32_get(wbuf, 
        OF_OBJECT_ABSOLUTE_OFFSET(obj, OF_MESSAGE_XID_OFFSET), xid);
    return OF_ERROR_NONE;
}

/****************************************************************
 *
 * Generic list operation implementations
 *
 ****************************************************************/

/**
 * Set up a child for appending to a parent list
 * @param parent The parent; must be a list object
 * @param child The child object; must be of type list element
 * @return OF_ERROR_
 *
 * Attaches the wire buffer of the parent to the child by pointing
 * the child to the end of the parent.
 * 
 * Set the wire length and type from the child.
 * Update the parent length adding the current child length
 *
 * After calling this function, the child object may be updated
 * resulting in changes to the parent's wire buffer
 * 
 */ 

int
of_list_append_bind(of_object_t *parent, of_object_t *child)
{
    if (parent == NULL || child == NULL ||
           parent->wire_object.wbuf == NULL) {
        return OF_ERROR_PARAM;
    }

    if (!of_object_can_grow(parent, parent->length + child->length)) {
        return OF_ERROR_RESOURCE;
    }

    object_child_attach(parent, child, parent->length, 
                        child->length);

    /* Update the wire length and type if needed */
    if (child->wire_length_set) {
        child->wire_length_set(child, child->length);
    }

    if (child->wire_type_set) {
        child->wire_type_set(child);
    }

    /* Update the parent's length */
    of_object_parent_length_update(parent, child->length);

    OF_LENGTH_CHECK_ASSERT(parent);

    return OF_ERROR_NONE;
}

/**
 * Generic atomic list append operation
 * @param list The list to which an item is being appended
 * @param item THe item to append to the list
 *
 * The contents of the item are copied to the end of the list.
 * Currently assumes the list is at the end of its parent.
 */
int
of_list_append(of_object_t *list, of_object_t *item)
{
    int new_len;

    new_len = list->length + item->length;

    if (!of_object_can_grow(list, new_len)) {
        return OF_ERROR_RESOURCE;
    }

    of_wire_buffer_grow(list->wire_object.wbuf,
                        OF_OBJECT_ABSOLUTE_OFFSET(list, new_len));

    MEMCPY(OF_OBJECT_BUFFER_INDEX(list, list->length),
           OF_OBJECT_BUFFER_INDEX(item, 0), item->length);

    /* Update the list's length */
    of_object_parent_length_update(list, item->length);

    OF_LENGTH_CHECK_ASSERT(list);

    return OF_ERROR_NONE;
}

/**
 * Generic list first function
 * @param parent The parent; must be a list object
 * @param child The child object; must be of type list element
 * @return OF_ERROR_RANGE if list is empty
 * @return OF_ERROR_
 *
 * Sets up the child to point to the first element in the list
 *
 * Child init must be called before this is called.
 *
 * @note TREAT AS PRIVATE
 * Does not fully initialized object
 */
int
of_list_first(of_object_t *parent, of_object_t *child)
{
    if (parent->length == 0) { /* Empty list */
        return OF_ERROR_RANGE;
    }

    object_child_attach(parent, child, 0, 0);

    return OF_ERROR_NONE;
}

/**
 * Return boolean indicating if child is pointing to last entry in parent
 * @param parent The parent; must be a list object
 * @param child The child object; must be of type list element
 * @return OF_ERROR_RANGE if list is empty
 * @return OF_ERROR_
 *
 */
static int
of_list_is_last(of_object_t *parent, of_object_t *child)
{
    if (child->wire_object.obj_offset + child->length >= 
        parent->wire_object.obj_offset + parent->length) {
        return 1;
    }

    return 0;
}

/**
 * Generic list next function
 * @param parent The parent; must be a list object
 * @param child The child object; must be of type list element
 * @return OF_ERROR_RANGE if at end of list
 * @return OF_ERROR_
 *
 * Advances the child to point to the subsequent element in the list.
 * The wire buffer object must not have been modified since the 
 * previous call to _first or _next.
 *
 * @note TREAT AS PRIVATE
 * Does not fully initialized object
 */ 
int
of_list_next(of_object_t *parent, of_object_t *child)
{
    int offset;

    LOCI_ASSERT(child->length > 0);

    /* Get offset of parent */
    if (of_list_is_last(parent, child)) {
        return OF_ERROR_RANGE; /* We were on the last object */
    }

    /* Offset is relative to parent start */
    offset = (child->wire_object.obj_offset - parent->wire_object.obj_offset) +
        child->length;
    object_child_attach(parent, child, offset, 0);

    return OF_ERROR_NONE;
}

void
of_object_wire_buffer_steal(of_object_t *obj, uint8_t **buffer)
{
    LOCI_ASSERT(obj != NULL);
    of_wire_buffer_steal(obj->wire_object.wbuf, buffer);
    obj->wire_object.wbuf = NULL;
}

#define _MAX_PARENT_ITERATIONS 4
/**
 * Iteratively update parent lengths thru hierarchy
 * @param obj The object whose length is being updated
 * @param delta The difference between the current and new lengths
 *
 * Note that this includes updating the object itself.  It will
 * iterate thru parents.
 *
 * Assumes delta > 0.
 */
void
of_object_parent_length_update(of_object_t *obj, int delta)
{
#ifndef NDEBUG
    int count = 0;
    of_wire_buffer_t *wbuf;  /* For debug asserts only */
#endif

    while (obj != NULL) {
        LOCI_ASSERT(count++ < _MAX_PARENT_ITERATIONS);
        obj->length += delta;
        if (obj->wire_length_set != NULL) {
            obj->wire_length_set(obj, obj->length);
        }
#ifndef NDEBUG
        wbuf = obj->wire_object.wbuf;
#endif

        /* Asserts for wire length checking */
        LOCI_ASSERT(obj->length + obj->wire_object.obj_offset <=
               WBUF_CURRENT_BYTES(wbuf));
        if (obj->parent == NULL) {
            LOCI_ASSERT(obj->length + obj->wire_object.obj_offset ==
                   WBUF_CURRENT_BYTES(wbuf));
        }

        obj = obj->parent;
    }
}

/**
 * Use the type/length from the wire buffer and init the object
 * @param obj The object being initialized
 * @param base_object_id If > 0, this indicates the base object
 * @param max_len If > 0, the max length to expect for the obj
 * type for inheritance checking
 * @return OF_ERROR_
 *
 * Used for inheritance type objects such as actions and OXMs
 * The type is checked and if valid, the object is initialized.
 * Then the length is taken from the buffer.
 *
 * Note that the object version must already be properly set.
 */
int
of_object_wire_init(of_object_t *obj, of_object_id_t base_object_id,
                    int max_len)
{
    if (obj->wire_type_get != NULL) {
        of_object_id_t id;
        obj->wire_type_get(obj, &id);
        if (!of_wire_id_valid(id, base_object_id)) {
            return OF_ERROR_PARSE;
        }
        obj->object_id = id;
        /* Call the init function for this object type; do not push to wire */
        of_object_init_map[id]((of_object_t *)(obj), obj->version, -1, 0);
    }
    if (obj->wire_length_get != NULL) {
        int length;
        obj->wire_length_get(obj, &length);
        if (length < 0 || (max_len > 0 && length > max_len)) {
            return OF_ERROR_PARSE;
        }
        obj->length = length;
    } else {
        /* @fixme Does this cover everything else? */
        obj->length = of_object_fixed_len[obj->version][base_object_id];
    }

    return OF_ERROR_NONE;
}

/*
 * Set member:
 *    get_wbuf_extent
 *    find offset of start of member
 *    if offset is at wbuf_extent (append new data)
 *        copy data at extent
 *        update parent length
 *    else
 *        find length of current entry
 *        move from end of current to extent to create (or remove) space
 *        copy data to offset
 *        update my length -- NEED LOCAL INFO TO DO THIS for some cases
 */

/* Also need: get offset of member for all combinations */
/* Also need: get length of member for all combinations */
#if 0
/**
 * Append the wire buffer data from src to the end of dst's wire buffer
 */
int
of_object_append_buffer(of_object_t *dst, of_object_t *src)
{
    of_wire_buffer_t *s_wbuf, *d_wbuf;
    int orig_len, dst_offset, src_offset;

    d_wbuf = OF_OBJECT_TO_WBUF(dst);
    s_wbuf = OF_OBJECT_TO_WBUF(src);
    dst_offset = dst->wire_object.obj_offset + dst_length;
    src_offset = src->wire_object.obj_offset;
    OF_WIRE_BUFFER_INIT_CHECK(d_wbuf, dst_offset + src->length);
    MEMCPY(OF_WBUF_BUFFER_POINTER(d_wbuf, dst_offset),
           OF_WBUF_BUFFER_POINTER(s_wbuf, 0), src->length);

    orig_len = dst->length;
    dst->length += src->length;

    return OF_ERROR_NONE;
}

/**
 * Set the length of the actions object in a packet_in object
 */

int
of_packet_out_actions_length_set(of_packet_t *obj, int len)
{
    if (obj == NULL || obj->object_id != OF_PACKET_IN ||
        obj->wire_object.wbuf == NULL) {
        return OF_ERROR_PARAM;
    }

    obj->actions_len_set(obj, len);
}

int
_packet_out_data_offset_get(of_packet_t *obj)
{
    if (obj == NULL || obj->object_id != OF_PACKET_IN ||
        obj->wire_object.wbuf == NULL) {
        return -1;
    }

    return OF_PACKET_OUT_FIXED_LENGTH + _packet_out_actions_length_get(obj);
}


/**
 * Simple length derivation function
 *
 * Most variable length fields are alone at the end of a structure.
 * Their length is a simple calculation, just the total length of
 * the parent minus the length of the non-variable part of the 
 * parent's class type.
 *
 * @param parent The parent object
 * @param length (out) Where to store the length of the final 
 * variable length member
 */
int
of_object_simple_length_derive(of_object_t *obj, int *length)
{
    
}
#endif
