tsf_bool_t tsf_serial_in_man_read_existing_buffer()

in benchmarks/JetStream2/wasm/TSF/tsf_serial_in_man.c [206:341]


tsf_bool_t tsf_serial_in_man_read_existing_buffer(tsf_serial_in_man_t *in_man,
                                                  tsf_buffer_t *result) {
    tsf_type_t *type;
    tsf_bool_t res;
    uint8_t command;
    char buf[256];
    tsf_type_in_map_t *new_types;
    uint32_t n;
    
    for (;;) {
        if (!in_man->reader(in_man->arg, &command, sizeof(command))) {
            /* if the EOF happens here and only here, then the EOF
             * can be said to have been expected. */
            if (tsf_get_error_code() == TSF_E_UNEXPECTED_EOF) {
                tsf_set_error(TSF_E_EOF, NULL);
            }

            return tsf_false;
        }
        
        switch (command) {
        case TSF_SP_C_RESET_TYPES:
            /* first read the magic string */
            if (!in_man->reader(in_man->arg, buf, TSF_SP_MAGIC_SUFFIX_LEN)) {
                return tsf_false;
            }
                
            if (memcmp(buf,
                       TSF_SP_MAGIC_SUFFIX,
                       TSF_SP_MAGIC_SUFFIX_LEN)) {
                tsf_set_error(TSF_E_PARSE_ERROR,
                              "Bad magic header for TSF_SP_C_RESET_TYPES "
                              "command");
                return tsf_false;
            }
                
            new_types = tsf_type_in_map_create();
            if (new_types == NULL) {
                return tsf_false;
            }
            tsf_type_in_map_destroy(in_man->types);
            in_man->types = new_types;
            in_man->state = 0;
            in_man->types_byte_size = 0;
            break;
        case TSF_SP_C_NEW_TYPE:
            if (tsf_type_in_map_get_num_types(in_man->types)
                == tsf_limits_max_types(in_man->limits)) {
                tsf_set_error(TSF_E_PARSE_ERROR,
                              "Too many types in one stream");
                return tsf_false;
            }
                
            type = tsf_type_read(in_man->reader,
                                 in_man->arg,
                                 in_man->limits);
            if (type == NULL) {
                return tsf_false;
            }
                
            if (tsf_type_in_map_get_num_types(in_man->types)
                > in_man->state) {
                /* this should be a type that we've seen already, so
                 * just verify that it is the right one. */
                    
                if (!tsf_type_compare(
                        tsf_type_in_map_get_type(in_man->types,
                                                 in_man->state),
                        type)) {
                    tsf_set_error(TSF_E_UNEXPECTED_TYPE,
                                  "While in a seek-back state with "
                                  "state = " fui32 " and num_types = "
                                  fui32,
                                  in_man->state,
                                  tsf_type_in_map_get_num_types(
                                      in_man->types));
                    tsf_type_destroy(type);
                    return tsf_false;
                }
            } else {
                /* a new type, so append it to the map. */
                    
                if (in_man->types_byte_size +
                    tsf_type_get_byte_size(type)
                    > tsf_limits_max_total_type_size(in_man->limits)) {
                    tsf_set_error(TSF_E_PARSE_ERROR,
                                  "Total size of types in stream too big");
                    tsf_type_destroy(type);
                    return tsf_false;
                }
                    
                in_man->types_byte_size += tsf_type_get_byte_size(type);
                    
                for (n = in_man->num_cbacks; n --> 0;) {
                    in_man->cbacks[n].cback(in_man,
                                            type,
                                            in_man->cbacks[n].arg);
                }
                    
                res = tsf_type_in_map_append(in_man->types, type);
                if (!res) {
                    tsf_type_destroy(type);
                    return tsf_false;
                }
            }
                
            tsf_type_destroy(type);
                
            in_man->state++;
            
            break;
        case TSF_SP_C_DATA:
            return tsf_buffer_read_simple(result,
                                          in_man->types,
                                          in_man->reader,
                                          in_man->arg,
                                          in_man->limits);
        default:
            if (command & TSF_SP_C_CF_DATA_BIT) {
                return tsf_buffer_read_small_with_type_code(result,
                                                            command & ~TSF_SP_C_CF_DATA_BIT,
                                                            in_man->types,
                                                            in_man->reader,
                                                            in_man->arg,
                                                            in_man->limits);
            }
            
            tsf_set_error(TSF_E_PARSE_ERROR,
                          "Unexpected command read from serial stream: %u", (unsigned)command);
            return tsf_false;
        }
    }
    
    tsf_abort("Should never get here");
    return tsf_false;
}