/* Generated from
 * /jenkins/jobs/oi-userland/workspace/components/library/heimdal/heimdal-7.8.0/lib/hdb/hdb.asn1
 */
/* Do not edit */

#define ASN1_LIB

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
#include <krb5-types.h>
#include "hdb_asn1.h"
#include "hdb_asn1-priv.h"
#include <asn1_err.h>
#include <der.h>
#include <asn1-template.h>

#include <parse_units.h>

int ASN1CALL encode_HDB_Ext_KeySet(unsigned char* p HEIMDAL_UNUSED_ATTRIBUTE,
                                   size_t len HEIMDAL_UNUSED_ATTRIBUTE,
                                   const HDB_Ext_KeySet* data,
                                   size_t* size) {
  size_t ret HEIMDAL_UNUSED_ATTRIBUTE = 0;
  size_t l HEIMDAL_UNUSED_ATTRIBUTE;
  int i HEIMDAL_UNUSED_ATTRIBUTE, e HEIMDAL_UNUSED_ATTRIBUTE;

  for (i = (int)(data)->len - 1; i >= 0; --i) {
    size_t Top_tag_for_oldret = ret;
    ret = 0;
    e = encode_hdb_keyset(p, len, &(data)->val[i], &l);
    if (e)
      return e;
    p -= l;
    len -= l;
    ret += l;

    ret += Top_tag_for_oldret;
  }
  e = der_put_length_and_tag(p, len, ret, ASN1_C_UNIV, CONS, UT_Sequence, &l);
  if (e)
    return e;
  p -= l;
  len -= l;
  ret += l;

  *size = ret;
  return 0;
}

int ASN1CALL
decode_HDB_Ext_KeySet(const unsigned char* p HEIMDAL_UNUSED_ATTRIBUTE,
                      size_t len HEIMDAL_UNUSED_ATTRIBUTE,
                      HDB_Ext_KeySet* data,
                      size_t* size) {
  size_t ret = 0;
  size_t l HEIMDAL_UNUSED_ATTRIBUTE;
  int e HEIMDAL_UNUSED_ATTRIBUTE;

  memset(data, 0, sizeof(*data));
  {
    size_t Top_datalen, Top_oldlen;
    Der_type Top_type;
    e = der_match_tag_and_length(p, len, ASN1_C_UNIV, &Top_type, UT_Sequence,
                                 &Top_datalen, &l);
    if (e == 0 && Top_type != CONS) {
      e = ASN1_BAD_ID;
    }
    if (e)
      goto fail;
    p += l;
    len -= l;
    ret += l;
    Top_oldlen = len;
    if (Top_datalen > len) {
      e = ASN1_OVERRUN;
      goto fail;
    }
    len = Top_datalen;
    {
      size_t Top_Tag_origlen = len;
      size_t Top_Tag_oldret = ret;
      size_t Top_Tag_olen = 0;
      void* Top_Tag_tmp;
      ret = 0;
      (data)->len = 0;
      (data)->val = NULL;
      while (ret < Top_Tag_origlen) {
        size_t Top_Tag_nlen = Top_Tag_olen + sizeof(*((data)->val));
        if (Top_Tag_olen > Top_Tag_nlen) {
          e = ASN1_OVERFLOW;
          goto fail;
        }
        Top_Tag_olen = Top_Tag_nlen;
        Top_Tag_tmp = realloc((data)->val, Top_Tag_olen);
        if (Top_Tag_tmp == NULL) {
          e = ENOMEM;
          goto fail;
        }
        (data)->val = Top_Tag_tmp;
        e = decode_hdb_keyset(p, len, &(data)->val[(data)->len], &l);
        if (e)
          goto fail;
        p += l;
        len -= l;
        ret += l;
        (data)->len++;
        len = Top_Tag_origlen - ret;
      }
      ret += Top_Tag_oldret;
    }
    len = Top_oldlen - Top_datalen;
  }
  if (size)
    *size = ret;
  return 0;
fail:
  free_HDB_Ext_KeySet(data);
  return e;
}

void ASN1CALL free_HDB_Ext_KeySet(HDB_Ext_KeySet* data) {
  while ((data)->len) {
    free_hdb_keyset(&(data)->val[(data)->len - 1]);
    (data)->len--;
  }
  free((data)->val);
  (data)->val = NULL;
}

size_t ASN1CALL length_HDB_Ext_KeySet(const HDB_Ext_KeySet* data) {
  size_t ret = 0;
  {
    size_t Top_tag_oldret = ret;
    unsigned int n_Top_tag;
    ret = 0;
    for (n_Top_tag = (data)->len; n_Top_tag > 0; --n_Top_tag) {
      size_t Top_tag_for_oldret = ret;
      ret = 0;
      ret += length_hdb_keyset(&(data)->val[n_Top_tag - 1]);
      ret += Top_tag_for_oldret;
    }
    ret += Top_tag_oldret;
  }
  ret += 1 + der_length_len(ret);
  return ret;
}

int ASN1CALL copy_HDB_Ext_KeySet(const HDB_Ext_KeySet* from,
                                 HDB_Ext_KeySet* to) {
  memset(to, 0, sizeof(*to));
  if (((to)->val = malloc((from)->len * sizeof(*(to)->val))) == NULL &&
      (from)->len != 0)
    goto fail;
  for ((to)->len = 0; (to)->len < (from)->len; (to)->len++) {
    if (copy_hdb_keyset(&(from)->val[(to)->len], &(to)->val[(to)->len]))
      goto fail;
  }
  return 0;
fail:
  free_HDB_Ext_KeySet(to);
  return ENOMEM;
}

int ASN1CALL add_HDB_Ext_KeySet(HDB_Ext_KeySet* data,
                                const hdb_keyset* element) {
  int ret;
  void* ptr;

  ptr = realloc(data->val, (data->len + 1) * sizeof(data->val[0]));
  if (ptr == NULL)
    return ENOMEM;
  data->val = ptr;

  ret = copy_hdb_keyset(element, &data->val[data->len]);
  if (ret)
    return ret;
  data->len++;
  return 0;
}

int ASN1CALL remove_HDB_Ext_KeySet(HDB_Ext_KeySet* data, unsigned int element) {
  void* ptr;

  if (data->len == 0 || element >= data->len)
    return ASN1_OVERRUN;
  free_hdb_keyset(&data->val[element]);
  data->len--;
  if (element < data->len)
    memmove(&data->val[element], &data->val[element + 1],
            sizeof(data->val[0]) * (data->len - element));
  ptr = realloc(data->val, data->len * sizeof(data->val[0]));
  if (ptr != NULL || data->len == 0)
    data->val = ptr;
  return 0;
}
