Logo Search packages:      
Sourcecode: dballe version File versions

dba_err bufr_encoder_encode ( bufrex_raw  in,
dba_rawmsg  out 
)

Encode a BUFR message

Parameters:
in The bufrex_raw with the data to encode
out The dba_rawmsg that will hold the encoded data
Returns:
The error indicator for the function.
See also:
dba_err

Definition at line 247 of file bufr_encoder.c.

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

{
      dba_err err = DBA_OK;
      encoder e = NULL;
      bufrex_opcode ops = NULL;
      bufrex_opcode cur;
      int dslen;

      DBA_RUN_OR_RETURN(encoder_create(&e));
      e->in = in;
      e->out = out;

      /* Initialise the encoder with the list of variables to encode */
      e->nextvar = in->vars;
      e->vars_left = in->vars_count;

      DBA_RUN_OR_GOTO(fail, bufrex_raw_get_datadesc(e->in, &ops));
      if (ops == NULL)
      {
            /* Generate data description section from the variable list, if it was missing */
            int i;
            for (i = 0; i < e->vars_left; i++)
                  DBA_RUN_OR_GOTO(fail, bufrex_raw_append_datadesc(e->in, dba_var_code(e->nextvar[i])));

            /* Reread the descriptors */
            DBA_RUN_OR_GOTO(fail, bufrex_raw_get_datadesc(e->in, &ops));
      }

      /* Encode bufr section 0 (Indicator section) */
      DBA_RUN_OR_RETURN(encoder_raw_append(e, "BUFR\0\0\0\x03", 8));

      TRACE("sec0 ends at %d\n", e->out->len);
      e->sec1_start = e->out->len;

      /* Encode bufr section 1 (Identification section) */
      /* Length of section */
      DBA_RUN_OR_RETURN(encoder_add_bits(e, 18, 24));
      /* Master table number */
      DBA_RUN_OR_RETURN(encoder_append_byte(e, 0));
      /* Originating/generating sub-centre (defined by Originating/generating centre) */
      DBA_RUN_OR_RETURN(encoder_append_byte(e, 0));
      /* Originating/generating centre (Common Code tableC-1) */
      /*DBA_RUN_OR_RETURN(bufr_message_append_byte(e, 0xff));*/
      DBA_RUN_OR_RETURN(encoder_append_byte(e, e->in->opt.bufr.origin));
      /* Update sequence number (zero for original BUFR messages; incremented for updates) */
      DBA_RUN_OR_RETURN(encoder_append_byte(e, 0));
      /* Bit 1= 0 No optional section = 1 Optional section included Bits 2 ­ 8 set to zero (reserved) */
      DBA_RUN_OR_RETURN(encoder_append_byte(e, 0));

      /* Data category (BUFR Table A) */
      /* Data sub-category (defined by local ADP centres) */
      DBA_RUN_OR_RETURN(encoder_append_byte(e, e->in->type));
      DBA_RUN_OR_RETURN(encoder_append_byte(e, e->in->subtype));
      /* Version number of master tables used (currently 9 for WMO FM 94 BUFR tables) */
      DBA_RUN_OR_RETURN(encoder_append_byte(e, e->in->opt.bufr.master_table));
      /* Version number of local tables used to augment the master table in use */
      DBA_RUN_OR_RETURN(encoder_append_byte(e, e->in->opt.bufr.local_table));

      /* Year of century */
      DBA_RUN_OR_RETURN(encoder_append_byte(e, e->in->rep_year == 2000 ? 100 : (e->in->rep_year % 100)));
      /* Month */
      DBA_RUN_OR_RETURN(encoder_append_byte(e, e->in->rep_month));
      /* Day */
      DBA_RUN_OR_RETURN(encoder_append_byte(e, e->in->rep_day));
      /* Hour */
      DBA_RUN_OR_RETURN(encoder_append_byte(e, e->in->rep_hour));
      /* Minute */
      DBA_RUN_OR_RETURN(encoder_append_byte(e, e->in->rep_minute));
      /* Century */
      DBA_RUN_OR_RETURN(encoder_append_byte(e, e->in->rep_year / 100));

      TRACE("sec1 ends at %d\n", e->out->len);
      e->sec2_start = e->out->len;

      /* Encode BUFR section 2 (Optional section) */
      /* Nothing to do */

      TRACE("sec2 ends at %d\n", e->out->len);
      e->sec3_start = e->out->len;

      /* Encode BUFR section 3 (Data description section) */

      /* Count the number of items in the data descriptor section */
      for (cur = ops, dslen = 0; cur != NULL; cur = cur->next, dslen++)
            ;

      /* Length of section */
      DBA_RUN_OR_RETURN(encoder_add_bits(e, 8 + 2*dslen, 24));
      DBA_RUN_OR_RETURN(encoder_append_byte(e, 0));
      DBA_RUN_OR_RETURN(encoder_append_short(e, 1));
      DBA_RUN_OR_RETURN(encoder_append_byte(e, 1));
      
      /* Data descriptors */
      for (cur = ops; cur != NULL; cur = cur->next)
            DBA_RUN_OR_RETURN(encoder_append_short(e, cur->val));

      /* One padding byte to make the section even */
      DBA_RUN_OR_RETURN(encoder_append_byte(e, 0));

      TRACE("sec3 ends at %d\n", e->out->len);
      e->sec4_start = e->out->len;

      /* Encode BUFR section 4 (Data section) */

      /* Length of section (currently set to 0, will be filled in later) */
      DBA_RUN_OR_RETURN(encoder_add_bits(e, 0, 24));
      DBA_RUN_OR_RETURN(encoder_append_byte(e, 0));

      /* Encode the data */
      while (e->vars_left > 0)
      {
            DBA_RUN_OR_GOTO(fail, bufrex_opcode_prepend(&(e->ops), ops));

            DBA_RUN_OR_GOTO(fail, encoder_encode_data_section(e));

            if (e->ops != NULL)
            {
                  err = dba_error_consistency("not all operators have been encoded");
                  goto fail;
            }

            /* TODO: increase the count of subsets when there are more than one */
      }

      /* Write all the bits and pad the data section to reach an even length */
      DBA_RUN_OR_RETURN(encoder_flush(e));
      if ((e->out->len % 2) == 1)
            DBA_RUN_OR_RETURN(encoder_append_byte(e, 0));
      DBA_RUN_OR_RETURN(encoder_flush(e));

      /* Write the length of the section in its header */
      {
            uint32_t val = htonl(e->out->len - e->sec4_start);
            memcpy(e->out->buf + e->sec4_start, ((char*)&val) + 1, 3);

            TRACE("sec4 size %d\n", e->out->len - e->sec4_start);
      }

      TRACE("sec4 ends at %d\n", e->out->len);
      e->sec5_start = e->out->len;

      /* Encode section 5 (End section) */
      DBA_RUN_OR_RETURN(encoder_raw_append(e, "7777", 4));

      TRACE("sec5 ends at %d\n", e->out->len);

      /* Write the length of the BUFR message in its header */
      {
            uint32_t val = htonl(e->out->len);
            memcpy(e->out->buf + 4, ((char*)&val) + 1, 3);

            TRACE("msg size %d\n", e->out->len);
      }

      e->out->encoding = BUFR;

      return dba_error_ok();

fail:
      if (e != NULL)
            encoder_delete(e);
      return err;
}


Generated by  Doxygen 1.6.0   Back to index