Logo Search packages:      
Sourcecode: dballe version File versions

dba_err bufr_decoder_decode ( dba_rawmsg  in,
bufrex_raw  out 
)

Decode a BUFR 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 190 of file bufr_decoder.c.

References bufrex_raw_get_datadesc(), DBA_RUN_OR_GOTO, and DBA_RUN_OR_RETURN.

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

      bufrex_raw_reset(out);

      DBA_RUN_OR_RETURN(decoder_create(&d));
      d->in = in;
      d->out = out;

      /* Read BUFR section 0 (Indicator section) */
      CHECK_AVAILABLE_DATA(d->in->buf, 8, "section 0 of BUFR message (indicator section)");
      d->sec1 = d->in->buf + 8;
      if (memcmp(d->in->buf, "BUFR", 4) != 0)
            PARSE_ERROR(d->in->buf, "data does not start with BUFR header (\"%.4s\" was read instead)", d->in->buf);
      TRACE(" -> is BUFR\n");

      /* Check the BUFR edition number */
      if (d->in->buf[7] != 3)
            PARSE_ERROR(d->in->buf + 7, "Only BUFR edition 3 is supported (this message is edition %d)", (unsigned)d->in->buf[7]);
      d->out->edition = d->in->buf[7];

      /* Read bufr section 1 (Identification section) */
      CHECK_AVAILABLE_DATA(d->sec1, 18, "section 1 of BUFR message (identification section)");
      d->sec2 = d->sec1 + (ntohl(*(uint32_t*)(d->sec1)) >> 8);
      if (d->sec2 > d->in->buf + d->in->len)
            PARSE_ERROR(d->sec1, "Section 1 claims to end past the end of the BUFR message");

      has_optional = d->sec1[7] & 0x80;
      d->out->opt.bufr.origin = d->sec1[5];
      d->out->opt.bufr.master_table = d->sec1[10];
      d->out->opt.bufr.local_table = d->sec1[11];
      d->out->type = (int)d->sec1[8];
      d->out->subtype = (int)d->sec1[9];

      d->out->rep_year = (int)d->sec1[12];
      d->out->rep_month = (int)d->sec1[13];
      d->out->rep_day = (int)d->sec1[14];
      d->out->rep_hour = (int)d->sec1[15];
      d->out->rep_minute = (int)d->sec1[16];
      if ((int)d->sec1[17] != 0)
            d->out->rep_year = (int)d->sec1[17] * 100 + (d->out->rep_year % 100);

      TRACE(" -> category %d subcategory %d\n", 
                        (int)d->sec1[8],
                        (int)d->sec1[9]);

      DBA_RUN_OR_GOTO(fail, bufrex_raw_load_tables(d->out));

#if 0
      fprintf(stderr, "S1 Len %d  table #%d  osc %d  oc %d  seq #%d  optsec %x\n",
                  bufr_sec1_len,
                  master_table,
                  (int)psec1[4],
                  (int)psec1[5],
                  (int)psec1[6],
                  (int)psec1[7]);
            
      fprintf(stderr, "S1 cat %d  subc %d  verm %d verl %d  %d/%d/%d %d:%d\n",
                  (int)psec1[8],
                  (int)psec1[9],
                  (int)psec1[10],
                  (int)psec1[11],

                  (int)psec1[12],
                  (int)psec1[13],
                  (int)psec1[14],
                  (int)psec1[15],
                  (int)psec1[16]);
#endif
      
      /* Read BUFR section 2 (Optional section) */
      if (has_optional)
      {
            CHECK_AVAILABLE_DATA(d->sec2, 4, "section 2 of BUFR message (optional section)");
            d->sec3 = d->sec2 + (ntohl(*(uint32_t*)(d->sec2)) >> 8);
            if (d->sec3 > d->in->buf + d->in->len)
                  PARSE_ERROR(d->sec2, "Section 2 claims to end past the end of the BUFR message");
      } else
            d->sec3 = d->sec2;

      /* Read BUFR section 3 (Data description section) */
      CHECK_AVAILABLE_DATA(d->sec3, 8, "section 3 of BUFR message (data description section)");
      d->sec4 = d->sec3 + (ntohl(*(uint32_t*)(d->sec3)) >> 8);
      if (d->sec4 > d->in->buf + d->in->len)
            PARSE_ERROR(d->sec3, "Section 3 claims to end past the end of the BUFR message");
      d->subsets = ntohs(*(uint16_t*)(d->sec3 + 4));
      for (i = 0; i < (d->sec4 - d->sec3 - 8)/2; i++)
      {
            dba_varcode var = (dba_varcode)ntohs(*(uint16_t*)(d->sec3 + 7 + (i*2)));
            DBA_RUN_OR_GOTO(fail, bufrex_raw_append_datadesc(d->out, var));
      }
      /*
      IFTRACE{
            TRACE(" -> data descriptor section: ");
            bufrex_opcode_print(msg->datadesc, stderr);
            TRACE("\n");
      }
      */

      /* Read BUFR section 4 (Data section) */
      CHECK_AVAILABLE_DATA(d->sec4, 4, "section 4 of BUFR message (data section)");

      d->sec5 = d->sec4 + (ntohl(*(uint32_t*)(d->sec4)) >> 8);
      if (d->sec5 > d->in->buf + d->in->len)
            PARSE_ERROR(d->sec4, "Section 4 claims to end past the end of the BUFR message");
      TRACE("section 4 is %d bytes long (%02x %02x %02x %02x)\n", (ntohl(*(uint32_t*)(d->sec4)) >> 8),
                  (unsigned int)*(d->sec4), (unsigned int)*(d->sec4+1), (unsigned int)*(d->sec4+2), (unsigned int)*(d->sec4+3));

      /* Initialize bit-decoding structures */
      d->cursor = d->sec4 + 4 - d->in->buf;

      /* Iterate on the number of subgroups */
      for (i = 0; i < d->subsets; i++)
      {
            DBA_RUN_OR_GOTO(fail, bufrex_raw_get_datadesc(d->out, &(d->ops)));
            DBA_RUN_OR_GOTO(fail, bufr_decode_data_section(d));
      }

      IFTRACE {
      if (decoder_bits_left(d) > 15)
      {
            fprintf(stderr, "The data section of %s still contains %d unparsed bits\n",
                        d->in->file->name, decoder_bits_left(d));
            /*
            err = dba_error_parse(msg->file->name, POS + vec->cursor,
                        "the data section still contains %d unparsed bits",
                        bitvec_bits_left(vec));
            goto fail;
            */
      }
      }

      /* Read BUFR section 5 (Data section) */
      CHECK_AVAILABLE_DATA(d->sec5, 4, "section 5 of BUFR message (end section)");

      if (memcmp(d->sec5, "7777", 4) != 0)
            PARSE_ERROR(d->sec5, "section 5 does not contain '7777'");

      /* Copy the decoded attributes into the decoded variables */
      DBA_RUN_OR_GOTO(fail, bufrex_raw_apply_attributes(out));

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

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

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


Generated by  Doxygen 1.6.0   Back to index