/*
 * Copyright(c) 2021 to 2022 ZettaScale Technology and others
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
 * v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

#if defined(__IDLC__)

@nested @final
struct struct_nested {
    @external long b1;
};

@nested @final
union union_nested switch (short) {
 case 1: long n1;
 default: char n2;
};

typedef string<128> str128_t;
typedef union_nested union_nested_t;
typedef sequence<long> seqlong_t;

@nested @final
union test_union switch (short) {
  case 1:
    @external long u1;
  case 2:
    @external string u2;          // char * u2;
  case 3:
    @external string<128> u3;     // char (* u3)[129];
  case 4:
    @external struct_nested u4;
  case 5:
    @external union_nested u5;
  case 6:
    @external short u6[2];        // int16_t (* u6)[10]
  case 7:
    @external short u7[2][3];     // int16_t (* u7)[2][3]
  case 8:
    @external sequence<short> u8;
  case 9:
    @external str128_t u9;        // char (* u3)[129];
  case 10:
    @external union_nested_t u10;
  case 11:
    @external seqlong_t u11[2];
};

@topic @final
struct test_ext {
  test_union f[11];
};

#else

#include "dds/ddsrt/heap.h"
#include "common.h"
#include "test_union_external.h"

const dds_topic_descriptor_t *desc = &test_ext_desc;

void init_sample (void *s)
{
  test_ext *s1 = (test_ext *) s;

  s1->f[0]._d = 1;
  EXTA (s1->f[0]._u.u1, 123);

  s1->f[1]._d = 2;
  STRA (s1->f[1]._u.u2, STR128);

  s1->f[2]._d = 3;
  A (s1->f[2]._u.u3);
  STRCPY (*(s1->f[2]._u.u3), STR128);

  s1->f[3]._d = 4;
  A (s1->f[3]._u.u4);
  EXTA (s1->f[3]._u.u4->b1, 456);

  s1->f[4]._d = 5;
  A (s1->f[4]._u.u5);
  s1->f[4]._u.u5->_d = 1;
  s1->f[4]._u.u5->_u.n1 = 789;

  s1->f[5]._d = 6;
  A (s1->f[5]._u.u6);
  (*s1->f[5]._u.u6)[0] = 321;
  (*s1->f[5]._u.u6)[1] = 654;

  s1->f[6]._d = 7;
  A (s1->f[6]._u.u7);
  for (int n = 0; n < 6; n++)
    (*s1->f[6]._u.u7)[n / 3][n % 3] = 1000 * n;

  s1->f[7]._d = 8;
  A (s1->f[7]._u.u8);
  SEQA(*(s1->f[7]._u.u8), 3);
  for (int n = 0; n < 3; n++)
    s1->f[7]._u.u8->_buffer[n] = 100 * n;

  s1->f[8]._d = 9;
  A (s1->f[8]._u.u9);
  STRCPY (*(s1->f[8]._u.u9), STR128);

  s1->f[9]._d = 10;
  A (s1->f[9]._u.u10);
  s1->f[9]._u.u10->_d = 3;
  s1->f[9]._u.u10->_u.n2 = 'a';

  s1->f[10]._d = 11;
  A (s1->f[10]._u.u11);
  for (int n = 0; n < 2; n++)
  {
    SEQA((*(s1->f[10]._u.u11))[n], 3);
    for (int m = 0; m < 3; m++)
      (*s1->f[10]._u.u11)[n]._buffer[m] = 100 * n + m;
  }
}

int cmp_sample (const void *sa, const void *sb)
{
  test_ext *a = (test_ext *) sa;
  test_ext *b = (test_ext *) sb;

  CMP (a, b, f[0]._d, 1);
  CMPEXT (a, b, f[0]._u.u1, 123);

  CMP (a, b, f[1]._d, 2);
  CMPSTR (a, b, f[1]._u.u2, STR128);

  CMP (a, b, f[2]._d, 3);
  CMPEXTSTR (a, b, f[2]._u.u3, STR128);

  CMP (a, b, f[3]._d, 4);
  CMPEXTEXTF (a, b, f[3]._u.u4, b1, 456);

  CMP (a, b, f[4]._d, 5);
  CMPEXTF (a, b, f[4]._u.u5, _d, 1);
  CMPEXTF (a, b, f[4]._u.u5, _u.n1, 789);

  CMP (a, b, f[5]._d, 6);
  CMPEXTA (a, b, f[5]._u.u6, 0, 321);
  CMPEXTA (a, b, f[5]._u.u6, 1, 654);

  CMP (a, b, f[6]._d, 7);
  for (int n = 0; n < 6; n++)
    CMPEXTA2 (a, b, f[6]._u.u7, n / 3, n % 3, 1000 * n);

  CMP (a, b, f[7]._d, 8);
  for (int n = 0; n < 3; n++)
    CMP(a, b, f[7]._u.u8->_buffer[n], 100 * n);

  CMP (a, b, f[8]._d, 9);
  CMPEXTSTR (a, b, f[8]._u.u9, STR128);

  CMP (a, b, f[9]._d, 10);
  CMPEXTF (a, b, f[9]._u.u10, _d, 3);
  CMPEXTF (a, b, f[9]._u.u10, _u.n2, 'a');

  CMP (a, b, f[10]._d, 11);
  for (int n = 0; n < 2; n++)
    for (int m = 0; m < 3; m++)
      CMPEXTAF (a, b, f[10]._u.u11, n, _buffer[m], 100 * n + m);

  return 0;
}

NO_KEY_CMP

#endif
