Logo Search packages:      
Sourcecode: dballe version File versions

dba_err crex_decoder_decode ( dba_rawmsg  in,
bufrex_raw  out 
)

Decode a CREX message

Parameters:
in The dba_msgraw with the data to decode
out The bufrex_raw that will hold the decoded data
Return values:
opt A newly created bufr_options with informations about the decoding process. If NULL is passed, nothing will be returned. If a bufr_options is returned, it will need to be deleted with bufr_options_delete().
Returns:
The error indicator for the function.
See also:
dba_err

Definition at line 134 of file crex_decoder.c.

References bufrex_raw_get_datadesc(), crex_decoder_decode(), dba_error_consistency, DBA_FAIL_GOTO, DBA_RUN_OR_GOTO, and DBA_RUN_OR_RETURN.

Referenced by bufrex_raw_decode(), and crex_decoder_decode().

{
      dba_err err;
      decoder d = NULL;
      int i;

      DBA_RUN_OR_RETURN(decoder_create(&d));
      d->in = in;
      d->out = out;
      d->cur = in->buf;
      
      /* Read crex section 0 (Indicator section) */
      CHECK_AVAILABLE_DATA(6, "initial header of CREX message");
      if (strncmp((const char*)d->cur, "CREX++", 6) != 0)
            PARSE_ERROR("data does not start with CREX header (\"%.6s\" was read instead)", d->in->buf);

      SKIP_DATA_AND_SPACES(6);
      TRACE(" -> is CREX\n");

      /* Read crex section 1 (Data description section) */

      CHECK_EOF("start of section 1");
      d->sec1_start = d->cur - d->in->buf;

      /* T<version> */
      if (*d->cur != 'T')
            PARSE_ERROR("version not found in CREX data description");

      {
            char edition[11];
            for (i = 0; i < 10 && d->cur < (d->in->buf + d->in->len) && !isspace(*d->cur); d->cur++, i++)
                  edition[i] = *d->cur;
            edition[i] = 0;

            if (sscanf(edition, "T%02d%02d%02d",
                              &(d->out->opt.crex.master_table),
                              &(d->out->edition),
                              &(d->out->opt.crex.table)) != 3)
                  DBA_FAIL_GOTO(fail, dba_error_consistency("Edition (T%s) is not in format Ttteevv", edition+1));
            
            SKIP_SPACES();
            TRACE(" -> edition %d\n", strtol(edition + 1, 0, 10));
      }

      /* A<atable code> */
      CHECK_EOF("A code");
      if (*d->cur != 'A')
            PARSE_ERROR("A Table informations not found in CREX data description");
      {
            char atable[20];
            int val;
            for (i = 0, d->cur++; d->cur < (d->in->buf + d->in->len) && i < 10 && isdigit(*d->cur); d->cur++, i++)
                  atable[i] = *d->cur;
            atable[i] = 0;
            val = strtol(atable, 0, 10);
            switch (strlen(atable))
            {
                  case 3:
                        d->out->type = val;
                        d->out->subtype = 0;
                        TRACE(" -> category %d\n", strtol(atable, 0, 10));
                        break;
                  case 6:
                        d->out->type = val / 1000;
                        d->out->subtype = val % 1000;
                        TRACE(" -> category %d, subcategory %d\n", val / 1000, val % 1000);
                        break;
                  default:
                        err = dba_error_consistency("Cannot parse an A table indicator %d digits long", strlen(atable));
                        goto fail;
            }
      }
      SKIP_SPACES();

      /* Load tables and set category/subcategory */
      DBA_RUN_OR_GOTO(fail, bufrex_raw_load_tables(d->out));

      /* data descriptors followed by (E?)\+\+ */
      CHECK_EOF("data descriptor section");

      d->has_check_digit = 0;
      while (1)
      {
            if (*d->cur == 'B' || *d->cur == 'R' || *d->cur == 'C' || *d->cur == 'D')
            {
                  dba_varcode var;
                  CHECK_AVAILABLE_DATA(6, "one data descriptor");
                  var = dba_descriptor_code((const char*)d->cur);
                  DBA_RUN_OR_GOTO(fail, bufrex_raw_append_datadesc(d->out, var));
                  SKIP_DATA_AND_SPACES(6);
            }
            else if (*d->cur == 'E')
            {
                  d->has_check_digit = 1;
                  d->expected_check_digit = 1;
                  SKIP_DATA_AND_SPACES(1);
            }
            else if (*d->cur == '+')
            {
                  CHECK_AVAILABLE_DATA(1, "end of data descriptor section");
                  if (*(d->cur+1) != '+')
                        PARSE_ERROR("data section ends with only one '+'");
                  SKIP_DATA_AND_SPACES(2);
                  break;
            }
      }
      IFTRACE{
            bufrex_opcode ops = NULL;
            TRACE(" -> data descriptor section: ");
            DBA_RUN_OR_GOTO(fail, bufrex_raw_get_datadesc(d->out, &ops));
            bufrex_opcode_print(ops, stderr);
            bufrex_opcode_delete(&ops);
            TRACE("\n");
      }

      /* Decode crex section 2 */
      CHECK_EOF("data section");
      d->sec2_start = d->cur - d->in->buf;
      while (1)
      {
            DBA_RUN_OR_GOTO(fail, bufrex_raw_get_datadesc(d->out, &(d->ops)));
            DBA_RUN_OR_GOTO(fail, crex_decoder_parse_data_section(d));
            SKIP_SPACES();
            CHECK_EOF("end of data section");

            if (*d->cur != '+')
                  PARSE_ERROR("there should be a '+' at the end of the data section");
            d->cur++;

            /* Peek at the next character to see if it's end of section */
            CHECK_EOF("end of data section");
            if (*d->cur == '+')
            {
                  d->cur++;
                  break;
            }
      }
      SKIP_SPACES();

      /* Decode crex optional section 3 */
      CHECK_AVAILABLE_DATA(4, "CREX optional section 3 or end of CREX message");
      d->sec3_start = d->cur - d->in->buf;
      if (strncmp((const char*)d->cur, "SUPP", 4) == 0)
      {
            for (d->cur += 4; strncmp((const char*)d->cur, "++", 2) != 0; d->cur++)
                  CHECK_AVAILABLE_DATA(2, "end of CREX optional section 3");
            SKIP_SPACES();
      }

      /* Decode crex end section 4 */
      CHECK_AVAILABLE_DATA(4, "end of CREX message");
      d->sec4_start = d->cur - d->in->buf;
      if (strncmp((const char*)d->cur, "7777", 4) != 0)
            PARSE_ERROR("unexpected data after data section or optional section 3");

      if (d != NULL)
            decoder_delete(d);
      return dba_error_ok();

fail:
      TRACE(" -> crex_decoder_parse failed.\n");

      if (d != NULL)
            decoder_delete(d);
      return err;
}


Generated by  Doxygen 1.6.0   Back to index