void write_filter(cmp_ctx_t *ctx, uint32_t id, uint32_t mask) { bool rtr = false, ide = false; if ((id & CAN_FRAME_RTR_FLAG) != 0) { rtr = true; } if ((id & CAN_FRAME_EXT_FLAG) != 0) { ide = true; id &= CAN_FRAME_EXT_ID_MASK; } else { id &= CAN_FRAME_STD_ID_MASK; } cmp_write_array(ctx, 6); cmp_write_bool(ctx, ide); cmp_write_bool(ctx, rtr); cmp_write_uint(ctx, id); rtr = false; ide = false; if ((mask & CAN_FRAME_RTR_FLAG) != 0) { rtr = true; } if ((mask & CAN_FRAME_EXT_FLAG) != 0) { ide = true; mask &= CAN_FRAME_EXT_ID_MASK; } else { mask &= CAN_FRAME_STD_ID_MASK; } cmp_write_bool(ctx, ide); cmp_write_bool(ctx, rtr); cmp_write_uint(ctx, mask); }
static void stream_thread(void *p) { chRegSetThreadName("stream"); static uint8_t buffer[64]; static char topic_name[TOPIC_NAME_LEN]; cmp_ctx_t ctx; cmp_mem_access_t mem; ip_addr_t server; (void) p; STREAM_HOST(&server); while (1) { motor_driver_t *drv_list; uint16_t drv_list_len; motor_manager_get_list(&motor_manager, &drv_list, &drv_list_len); int i; for (i = 0; i < drv_list_len; i++) { if (motor_driver_get_stream_change_status(&drv_list[i]) != 0) { if (motor_driver_get_stream_change_status(&drv_list[i]) & (1 << MOTOR_STREAM_CURRENT_SETPT)) { strncpy(topic_name, "actuator/", TOPIC_NAME_LEN); strncat(topic_name, motor_driver_get_id(&drv_list[i]), TOPIC_NAME_LEN); strncat(topic_name, "/current_setp", TOPIC_NAME_LEN); message_write_header(&ctx, &mem, buffer, sizeof(buffer), topic_name); cmp_write_float(&ctx, motor_driver_get_and_clear_stream_value(&drv_list[i], MOTOR_STREAM_CURRENT_SETPT)); message_transmit(buffer, cmp_mem_access_get_pos(&mem), &server, STREAM_PORT); } if (motor_driver_get_stream_change_status(&drv_list[i]) & (1 << MOTOR_STREAM_CURRENT)) { strncpy(topic_name, "actuator/", TOPIC_NAME_LEN); strncat(topic_name, motor_driver_get_id(&drv_list[i]), TOPIC_NAME_LEN); strncat(topic_name, "/current", TOPIC_NAME_LEN); message_write_header(&ctx, &mem, buffer, sizeof(buffer), topic_name); cmp_write_float(&ctx, motor_driver_get_and_clear_stream_value(&drv_list[i], MOTOR_STREAM_CURRENT)); message_transmit(buffer, cmp_mem_access_get_pos(&mem), &server, STREAM_PORT); } if (motor_driver_get_stream_change_status(&drv_list[i]) & (1 << MOTOR_STREAM_MOTOR_VOLTAGE)) { strncpy(topic_name, "actuator/", TOPIC_NAME_LEN); strncat(topic_name, motor_driver_get_id(&drv_list[i]), TOPIC_NAME_LEN); strncat(topic_name, "/voltage", TOPIC_NAME_LEN); message_write_header(&ctx, &mem, buffer, sizeof(buffer), topic_name); cmp_write_float(&ctx, motor_driver_get_and_clear_stream_value(&drv_list[i], MOTOR_STREAM_MOTOR_VOLTAGE)); message_transmit(buffer, cmp_mem_access_get_pos(&mem), &server, STREAM_PORT); } if (motor_driver_get_stream_change_status(&drv_list[i]) & (1 << MOTOR_STREAM_VELOCITY_SETPT)) { strncpy(topic_name, "actuator/", TOPIC_NAME_LEN); strncat(topic_name, motor_driver_get_id(&drv_list[i]), TOPIC_NAME_LEN); strncat(topic_name, "/velocity_setp", TOPIC_NAME_LEN); message_write_header(&ctx, &mem, buffer, sizeof(buffer), topic_name); cmp_write_float(&ctx, motor_driver_get_and_clear_stream_value(&drv_list[i], MOTOR_STREAM_VELOCITY_SETPT)); message_transmit(buffer, cmp_mem_access_get_pos(&mem), &server, STREAM_PORT); } if (motor_driver_get_stream_change_status(&drv_list[i]) & (1 << MOTOR_STREAM_VELOCITY)) { strncpy(topic_name, "actuator/", TOPIC_NAME_LEN); strncat(topic_name, motor_driver_get_id(&drv_list[i]), TOPIC_NAME_LEN); strncat(topic_name, "/velocity", TOPIC_NAME_LEN); message_write_header(&ctx, &mem, buffer, sizeof(buffer), topic_name); cmp_write_float(&ctx, motor_driver_get_and_clear_stream_value(&drv_list[i], MOTOR_STREAM_VELOCITY)); message_transmit(buffer, cmp_mem_access_get_pos(&mem), &server, STREAM_PORT); } if (motor_driver_get_stream_change_status(&drv_list[i]) & (1 << MOTOR_STREAM_POSITION_SETPT)) { strncpy(topic_name, "actuator/", TOPIC_NAME_LEN); strncat(topic_name, motor_driver_get_id(&drv_list[i]), TOPIC_NAME_LEN); strncat(topic_name, "/position_setp", TOPIC_NAME_LEN); message_write_header(&ctx, &mem, buffer, sizeof(buffer), topic_name); cmp_write_float(&ctx, motor_driver_get_and_clear_stream_value(&drv_list[i], MOTOR_STREAM_POSITION_SETPT)); message_transmit(buffer, cmp_mem_access_get_pos(&mem), &server, STREAM_PORT); } if (motor_driver_get_stream_change_status(&drv_list[i]) & (1 << MOTOR_STREAM_POSITION)) { strncpy(topic_name, "actuator/", TOPIC_NAME_LEN); strncat(topic_name, motor_driver_get_id(&drv_list[i]), TOPIC_NAME_LEN); strncat(topic_name, "/position", TOPIC_NAME_LEN); message_write_header(&ctx, &mem, buffer, sizeof(buffer), topic_name); cmp_write_float(&ctx, motor_driver_get_and_clear_stream_value(&drv_list[i], MOTOR_STREAM_POSITION)); message_transmit(buffer, cmp_mem_access_get_pos(&mem), &server, STREAM_PORT); } if (motor_driver_get_stream_change_status(&drv_list[i]) & (1 << MOTOR_STREAM_INDEX)) { strncpy(topic_name, "actuator/", TOPIC_NAME_LEN); strncat(topic_name, motor_driver_get_id(&drv_list[i]), TOPIC_NAME_LEN); strncat(topic_name, "/index", TOPIC_NAME_LEN); message_write_header(&ctx, &mem, buffer, sizeof(buffer), topic_name); cmp_write_array(&ctx, 2); cmp_write_float(&ctx, motor_driver_get_and_clear_stream_value(&drv_list[i], MOTOR_STREAM_INDEX)); cmp_write_uint(&ctx, drv_list[i].stream.value_stream_index_update_count); message_transmit(buffer, cmp_mem_access_get_pos(&mem), &server, STREAM_PORT); } if (motor_driver_get_stream_change_status(&drv_list[i]) & (1 << MOTOR_STREAM_MOTOR_ENCODER)) { strncpy(topic_name, "actuator/", TOPIC_NAME_LEN); strncat(topic_name, motor_driver_get_id(&drv_list[i]), TOPIC_NAME_LEN); strncat(topic_name, "/encoder", TOPIC_NAME_LEN); message_write_header(&ctx, &mem, buffer, sizeof(buffer), topic_name); cmp_write_float(&ctx, motor_driver_get_and_clear_stream_value(&drv_list[i], MOTOR_STREAM_MOTOR_ENCODER)); message_transmit(buffer, cmp_mem_access_get_pos(&mem), &server, STREAM_PORT); } if (motor_driver_get_stream_change_status(&drv_list[i]) & (1 << MOTOR_STREAM_MOTOR_TORQUE)) { strncpy(topic_name, "actuator/", TOPIC_NAME_LEN); strncat(topic_name, motor_driver_get_id(&drv_list[i]), TOPIC_NAME_LEN); strncat(topic_name, "/torque", TOPIC_NAME_LEN); message_write_header(&ctx, &mem, buffer, sizeof(buffer), topic_name); cmp_write_float(&ctx, motor_driver_get_and_clear_stream_value(&drv_list[i], MOTOR_STREAM_MOTOR_TORQUE)); message_transmit(buffer, cmp_mem_access_get_pos(&mem), &server, STREAM_PORT); } } } chThdSleepMilliseconds(STREAM_TIMESTEP_MS); } }
static THD_FUNCTION(stream, arg) { (void)arg; chRegSetThreadName("stream"); static event_listener_t sensor_event_listener; chEvtRegisterMaskWithFlags(&sensor_events, &sensor_event_listener, (eventmask_t)ONBOARDSENSOR_EVENT, (eventflags_t)SENSOR_EVENT_MPU6000 | SENSOR_EVENT_H3LIS331DL | SENSOR_EVENT_HMC5883L | SENSOR_EVENT_MS5611); static char dtgrm[100]; static cmp_mem_access_t mem; static cmp_ctx_t cmp; while (1) { eventmask_t events = chEvtWaitAny(ONBOARDSENSOR_EVENT); if (events & ONBOARDSENSOR_EVENT) { eventflags_t event_flags = chEvtGetAndClearFlags(&sensor_event_listener); if (event_flags & SENSOR_EVENT_MPU6000) { rate_gyro_sample_t gyro; accelerometer_sample_t acc; onboard_sensor_get_mpu6000_gyro_sample(&gyro); onboard_sensor_get_mpu6000_acc_sample(&acc); cmp_mem_access_init(&cmp, &mem, dtgrm, sizeof(dtgrm)); bool err = false; err = err || !msg_header_write(&cmp, "imu"); err = err || !cmp_write_map(&cmp, 3); err = err || !CMP_WRITE_C_STRING(cmp, "gyro"); err = err || !cmp_write_array(&cmp, 3); err = err || !cmp_write_float(&cmp, gyro.rate[0]); err = err || !cmp_write_float(&cmp, gyro.rate[1]); err = err || !cmp_write_float(&cmp, gyro.rate[2]); err = err || !CMP_WRITE_C_STRING(cmp, "acc"); err = err || !cmp_write_array(&cmp, 3); err = err || !cmp_write_float(&cmp, acc.acceleration[0]); err = err || !cmp_write_float(&cmp, acc.acceleration[1]); err = err || !cmp_write_float(&cmp, acc.acceleration[2]); err = err || !CMP_WRITE_C_STRING(cmp, "time"); err = err || !cmp_write_uint(&cmp, gyro.timestamp); if (!err) { datagram_message_send(dtgrm, cmp_mem_access_get_pos(&mem)); } cmp_mem_access_init(&cmp, &mem, dtgrm, sizeof(dtgrm)); err = false; float att[4]; attitude_determination_get_attitude(att); err = err || !msg_header_write(&cmp, "att"); err = err || !cmp_write_array(&cmp, 4); err = err || !cmp_write_float(&cmp, att[0]); err = err || !cmp_write_float(&cmp, att[1]); err = err || !cmp_write_float(&cmp, att[2]); err = err || !cmp_write_float(&cmp, att[3]); if (!err) { datagram_message_send(dtgrm, cmp_mem_access_get_pos(&mem)); } } if (event_flags & SENSOR_EVENT_HMC5883L) { magnetometer_sample_t magnetometer; onboard_sensor_get_hmc5883l_mag_sample(&magnetometer); cmp_mem_access_init(&cmp, &mem, dtgrm, sizeof(dtgrm)); bool err = false; err = err || !msg_header_write(&cmp, "mag"); err = err || !cmp_write_map(&cmp, 2); err = err || !CMP_WRITE_C_STRING(cmp, "field"); err = err || !cmp_write_array(&cmp, 3); err = err || !cmp_write_float(&cmp, magnetometer.magnetic_field[0]); err = err || !cmp_write_float(&cmp, magnetometer.magnetic_field[1]); err = err || !cmp_write_float(&cmp, magnetometer.magnetic_field[2]); err = err || !CMP_WRITE_C_STRING(cmp, "time"); err = err || !cmp_write_uint(&cmp, magnetometer.timestamp); if (!err) { datagram_message_send(dtgrm, cmp_mem_access_get_pos(&mem)); } } if (event_flags & SENSOR_EVENT_H3LIS331DL) { accelerometer_sample_t acc; onboard_sensor_get_h3lis331dl_acc_sample(&acc); cmp_mem_access_init(&cmp, &mem, dtgrm, sizeof(dtgrm)); bool err = false; err = err || !msg_header_write(&cmp, "hi_acc"); err = err || !cmp_write_map(&cmp, 2); err = err || !CMP_WRITE_C_STRING(cmp, "acc"); err = err || !cmp_write_array(&cmp, 3); err = err || !cmp_write_float(&cmp, acc.acceleration[0]); err = err || !cmp_write_float(&cmp, acc.acceleration[1]); err = err || !cmp_write_float(&cmp, acc.acceleration[2]); err = err || !CMP_WRITE_C_STRING(cmp, "time"); err = err || !cmp_write_uint(&cmp, acc.timestamp); if (!err) { datagram_message_send(dtgrm, cmp_mem_access_get_pos(&mem)); } } if (event_flags & SENSOR_EVENT_MS5611) { barometer_sample_t baro; onboard_sensor_get_ms5511_baro_sample(&baro); cmp_mem_access_init(&cmp, &mem, dtgrm, sizeof(dtgrm)); bool err = false; err = err || !msg_header_write(&cmp, "baro"); err = err || !cmp_write_map(&cmp, 3); err = err || !CMP_WRITE_C_STRING(cmp, "static_press"); err = err || !cmp_write_float(&cmp, baro.pressure); err = err || !CMP_WRITE_C_STRING(cmp, "air_temp"); err = err || !cmp_write_float(&cmp, baro.temperature); err = err || !CMP_WRITE_C_STRING(cmp, "time"); err = err || !cmp_write_uint(&cmp, baro.timestamp); if (!err) { datagram_message_send(dtgrm, cmp_mem_access_get_pos(&mem)); } } } // ONBOARDSENSOR_EVENT } }
int main(void) { FILE *fh = NULL; cmp_ctx_t cmp; uint16_t year = 1983; uint8_t month = 5; uint8_t day = 28; int64_t sint = 0; uint64_t uint = 0; float flt = 0.0f; double dbl = 0.0; bool boolean = false; uint8_t fake_bool = 0; uint32_t string_size = 0; uint32_t array_size = 0; uint32_t binary_size = 0; uint32_t map_size = 0; int8_t ext_type = 0; uint32_t ext_size = 0; char sbuf[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; fh = fopen("cmp_data.dat", "w+b"); if (fh == NULL) error_and_exit("Error opening data.dat"); cmp_init(&cmp, fh, file_reader, file_skipper, file_writer); /* * When you write an array, you first specify the number of array * elements, then you write that many elements. */ if (!cmp_write_array(&cmp, 9)) error_and_exit(cmp_strerror(&cmp)); if (!cmp_write_sint(&cmp, -14)) error_and_exit(cmp_strerror(&cmp)); if (!cmp_write_uint(&cmp, 38)) error_and_exit(cmp_strerror(&cmp)); if (!cmp_write_float(&cmp, 1.8f)) error_and_exit(cmp_strerror(&cmp)); if (!cmp_write_double(&cmp, 300.4)) error_and_exit(cmp_strerror(&cmp)); if (!cmp_write_nil(&cmp)) error_and_exit(cmp_strerror(&cmp)); if (!cmp_write_true(&cmp)) error_and_exit(cmp_strerror(&cmp)); if (!cmp_write_false(&cmp)) error_and_exit(cmp_strerror(&cmp)); if (!cmp_write_bool(&cmp, false)) error_and_exit(cmp_strerror(&cmp)); if (!cmp_write_u8_as_bool(&cmp, 1)) error_and_exit(cmp_strerror(&cmp)); /* Array full */ /* * Maps work similar to arrays, but the length is in "pairs", so this * writes 2 pairs to the map. Subsequently, pairs are written in key, * value order. */ if (!cmp_write_map(&cmp, 2)) error_and_exit(cmp_strerror(&cmp)); /* You can write string data all at once... */ if (!cmp_write_str(&cmp, "Greeting", 8)) error_and_exit(cmp_strerror(&cmp)); if (!cmp_write_str(&cmp, "Hello", 5)) error_and_exit(cmp_strerror(&cmp)); if (!cmp_write_str(&cmp, "Name", 4)) error_and_exit(cmp_strerror(&cmp)); /* ...or in chunks */ if (!cmp_write_str_marker(&cmp, 5)) error_and_exit(cmp_strerror(&cmp)); if (file_writer(&cmp, "Li", 2) != 2) error_and_exit(strerror(errno)); if (file_writer(&cmp, "nus", 3) != 3) error_and_exit(strerror(errno)); /* Map full */ /* Binary data functions the same as string data */ if (!cmp_write_bin(&cmp, "MessagePack", 11)) error_and_exit(cmp_strerror(&cmp)); if (!cmp_write_bin_marker(&cmp, 8)) error_and_exit(cmp_strerror(&cmp)); if (file_writer(&cmp, "is ", 3) != 3) error_and_exit(strerror(errno)); if (file_writer(&cmp, "great", 5) != 5) error_and_exit(strerror(errno)); /* * With extended types, you can create your own custom types. Here we * create a simple date type. */ /* cmp_write_ext_marker(type, size) */ if (!cmp_write_ext_marker(&cmp, 1, 4)) error_and_exit(cmp_strerror(&cmp)); file_writer(&cmp, &year, sizeof(uint16_t)); file_writer(&cmp, &month, sizeof(uint8_t)); file_writer(&cmp, &day, sizeof(uint8_t)); /* Now we can read the data back just as easily */ rewind(fh); if (!cmp_read_array(&cmp, &array_size)) error_and_exit(cmp_strerror(&cmp)); if (array_size != 9) error_and_exit("Array size was not 9"); if (!cmp_read_sinteger(&cmp, &sint)) error_and_exit(cmp_strerror(&cmp)); if (sint != -14) error_and_exit("Signed int was not -14"); if (!cmp_read_uinteger(&cmp, &uint)) error_and_exit(cmp_strerror(&cmp)); if (uint != 38) error_and_exit("Unsigned int was not 38"); if (!cmp_read_float(&cmp, &flt)) error_and_exit(cmp_strerror(&cmp)); if (flt != 1.8f) error_and_exit("Float was not 1.8f"); if (!cmp_read_double(&cmp, &dbl)) error_and_exit(cmp_strerror(&cmp)); if (dbl != 300.4) error_and_exit("Double was not 300.f"); if (!cmp_read_nil(&cmp)) error_and_exit(cmp_strerror(&cmp)); if (!cmp_read_bool(&cmp, &boolean)) error_and_exit(cmp_strerror(&cmp)); if (boolean != true) error_and_exit("First boolean was not true"); if (!cmp_read_bool(&cmp, &boolean)) error_and_exit(cmp_strerror(&cmp)); if (boolean != false) error_and_exit("Second boolean was not false"); if (!cmp_read_bool(&cmp, &boolean)) error_and_exit(cmp_strerror(&cmp)); if (boolean != false) error_and_exit("Third boolean was not false"); if (!cmp_read_bool_as_u8(&cmp, &fake_bool)) error_and_exit(cmp_strerror(&cmp)); if (fake_bool != 1) { fprintf(stderr, "%u.\n", fake_bool); error_and_exit("Third boolean (u8) was not 1"); } if (!cmp_read_map(&cmp, &map_size)) error_and_exit(cmp_strerror(&cmp)); if (map_size != 2) error_and_exit("Map size was not 2"); /* * String reading here. Note that normally strings are encoded using * UTF-8. I have cleverly restricted this example to ASCII, which overlaps * UTF-8 encoding, but this must not be assumed in real-world code. * * You can read strings in two ways. Either you can read the string's size * in bytes and then read the bytes manually... */ if (!cmp_read_str_size(&cmp, &string_size)) error_and_exit(cmp_strerror(&cmp)); if (string_size != 8) error_and_exit("Greeting string key size was not 8"); if (!read_bytes(sbuf, 8, fh)) error_and_exit(strerror(errno)); sbuf[string_size] = 0; if (strncmp(sbuf, "Greeting", 8) != 0) error_and_exit("Greeting string key name was not 'Greeting'"); /* * ...or you can set the maximum number of bytes to read and do it all in * one call. cmp_read_str will write no more than "size" bytes, including * the terminating NULL, to the passed buffer. If the string's size * exceeds the passed buffer size, the "size" input is set to the number of * bytes necessary, not including the terminating NULL. Otherwise, the * "size" input is set to the number of bytes written, not including the * terminating NULL. */ string_size = sizeof(sbuf); if (!cmp_read_str(&cmp, sbuf, &string_size)) error_and_exit(cmp_strerror(&cmp)); if (strncmp(sbuf, "Hello", 5) != 0) error_and_exit("Greeting string value was not 'Hello'"); string_size = sizeof(sbuf); if (!cmp_read_str(&cmp, sbuf, &string_size)) error_and_exit(cmp_strerror(&cmp)); if (strncmp(sbuf, "Name", 4) != 0) error_and_exit("Name key name was not 'Name'"); string_size = sizeof(sbuf); if (!cmp_read_str(&cmp, sbuf, &string_size)) error_and_exit(cmp_strerror(&cmp)); if (strncmp(sbuf, "Linus", 5) != 0) error_and_exit("Name key value was not 'Linus'"); memset(sbuf, 0, sizeof(sbuf)); binary_size = sizeof(sbuf); if (!cmp_read_bin(&cmp, &sbuf, &binary_size)) error_and_exit(cmp_strerror(&cmp)); if (memcmp(sbuf, "MessagePack", 11) != 0) error_and_exit("1st binary value was not 'MessagePack'"); memset(sbuf, 0, sizeof(sbuf)); binary_size = sizeof(sbuf); if (!cmp_read_bin(&cmp, &sbuf, &binary_size)) error_and_exit(cmp_strerror(&cmp)); if (memcmp(sbuf, "is great", 8) != 0) error_and_exit("2nd binary value was not 'is great'"); if (!cmp_read_ext_marker(&cmp, &ext_type, &ext_size)) error_and_exit(cmp_strerror(&cmp)); if (!read_bytes(&year, sizeof(uint16_t), fh)) error_and_exit(strerror(errno)); if (!read_bytes(&month, sizeof(uint8_t), fh)) error_and_exit(strerror(errno)); if (!read_bytes(&day, sizeof(uint8_t), fh)) error_and_exit(strerror(errno)); if (year != 1983) error_and_exit("Year was not 1983"); if (month != 5) error_and_exit("Month was not 5"); if (day != 28) error_and_exit("Day was not 28"); rewind(fh); /* Alternately, you can read objects until the stream is empty */ while (1) { cmp_object_t obj; if (!cmp_read_object(&cmp, &obj)) { if (feof(fh)) break; error_and_exit(cmp_strerror(&cmp)); } switch (obj.type) { case CMP_TYPE_POSITIVE_FIXNUM: case CMP_TYPE_UINT8: printf("Unsigned Integer: %u\n", obj.as.u8); break; case CMP_TYPE_FIXMAP: case CMP_TYPE_MAP16: case CMP_TYPE_MAP32: printf("Map: %u\n", obj.as.map_size); break; case CMP_TYPE_FIXARRAY: case CMP_TYPE_ARRAY16: case CMP_TYPE_ARRAY32: printf("Array: %u\n", obj.as.array_size); break; case CMP_TYPE_FIXSTR: case CMP_TYPE_STR8: case CMP_TYPE_STR16: case CMP_TYPE_STR32: if (!read_bytes(sbuf, obj.as.str_size, fh)) error_and_exit(strerror(errno)); sbuf[obj.as.str_size] = 0; printf("String: %s\n", sbuf); break; case CMP_TYPE_BIN8: case CMP_TYPE_BIN16: case CMP_TYPE_BIN32: memset(sbuf, 0, sizeof(sbuf)); if (!read_bytes(sbuf, obj.as.bin_size, fh)) error_and_exit(strerror(errno)); printf("Binary: %s\n", sbuf); break; case CMP_TYPE_NIL: printf("NULL\n"); break; case CMP_TYPE_BOOLEAN: if (obj.as.boolean) printf("Boolean: true\n"); else printf("Boolean: false\n"); break; case CMP_TYPE_EXT8: case CMP_TYPE_EXT16: case CMP_TYPE_EXT32: case CMP_TYPE_FIXEXT1: case CMP_TYPE_FIXEXT2: case CMP_TYPE_FIXEXT4: case CMP_TYPE_FIXEXT8: case CMP_TYPE_FIXEXT16: if (obj.as.ext.type == 1) { /* Date object */ if (!read_bytes(&year, sizeof(uint16_t), fh)) error_and_exit(strerror(errno)); if (!read_bytes(&month, sizeof(uint8_t), fh)) error_and_exit(strerror(errno)); if (!read_bytes(&day, sizeof(uint8_t), fh)) error_and_exit(strerror(errno)); printf("Date: %u/%u/%u\n", year, month, day); } else { printf("Extended type {%d, %u}: ", obj.as.ext.type, obj.as.ext.size ); while (obj.as.ext.size--) { read_bytes(sbuf, sizeof(uint8_t), fh); printf("%02x ", sbuf[0]); } printf("\n"); } break; case CMP_TYPE_FLOAT: printf("Float: %f\n", obj.as.flt); break; case CMP_TYPE_DOUBLE: printf("Double: %f\n", obj.as.dbl); break; case CMP_TYPE_UINT16: printf("Unsigned Integer: %u\n", obj.as.u16); break; case CMP_TYPE_UINT32: printf("Unsigned Integer: %u\n", obj.as.u32); break; case CMP_TYPE_UINT64: printf("Unsigned Integer: %" PRIu64 "\n", obj.as.u64); break; case CMP_TYPE_NEGATIVE_FIXNUM: case CMP_TYPE_SINT8: printf("Signed Integer: %d\n", obj.as.s8); break; case CMP_TYPE_SINT16: printf("Signed Integer: %d\n", obj.as.s16); break; case CMP_TYPE_SINT32: printf("Signed Integer: %d\n", obj.as.s32); break; case CMP_TYPE_SINT64: printf("Signed Integer: %" PRId64 "\n", obj.as.s64); break; default: printf("Unrecognized object type %u\n", obj.type); break; } } fclose(fh); return EXIT_SUCCESS; }