diff --git a/flatgeobuf.cpp b/flatgeobuf.cpp index be2a4964..7341857f 100644 --- a/flatgeobuf.cpp +++ b/flatgeobuf.cpp @@ -154,98 +154,104 @@ void readFeature(const FlatGeobuf::Feature *feature, long long feature_sequence_ std::vector full_keys; std::vector full_values; - // assume tabular schema with columns in header - size_t p_pos = 0; - while (p_pos < feature->properties()->size()) { - uint16_t col_idx; - memcpy(&col_idx, feature->properties()->data() + p_pos, sizeof(col_idx)); + if (feature == NULL) { + fprintf(stderr, "Can't happen: null geobuf feature\n"); + exit(EXIT_IMPOSSIBLE); + } + if (feature->properties() != NULL) { + // assume tabular schema with columns in header + size_t p_pos = 0; + while (p_pos < feature->properties()->size()) { + uint16_t col_idx; + memcpy(&col_idx, feature->properties()->data() + p_pos, sizeof(col_idx)); - // https://github.com/protomaps/tippecanoe/issues/7 - // check if column name is tippecanoe:minzoom, tippecanoe:maxzoom or tippecanoe:layer + // https://github.com/protomaps/tippecanoe/issues/7 + // check if column name is tippecanoe:minzoom, tippecanoe:maxzoom or tippecanoe:layer - FlatGeobuf::ColumnType col_type = h_column_types[col_idx]; + FlatGeobuf::ColumnType col_type = h_column_types[col_idx]; - serial_val sv; - if (col_type == FlatGeobuf::ColumnType_Byte) { - sv.type = mvt_sint; - int8_t byte_val; - memcpy(&byte_val, feature->properties()->data() + p_pos + sizeof(uint16_t), sizeof(byte_val)); - sv.s = std::to_string(byte_val); - p_pos += sizeof(uint16_t) + sizeof(byte_val); - } else if (col_type == FlatGeobuf::ColumnType_UByte) { - sv.type = mvt_uint; - uint8_t ubyte_val; - memcpy(&ubyte_val, feature->properties()->data() + p_pos + sizeof(uint16_t), sizeof(ubyte_val)); - sv.s = std::to_string(ubyte_val); - p_pos += sizeof(uint16_t) + sizeof(ubyte_val); - } else if (col_type == FlatGeobuf::ColumnType_Bool) { - sv.type = mvt_bool; - uint8_t bool_val; - memcpy(&bool_val, feature->properties()->data() + p_pos + sizeof(uint16_t), sizeof(bool_val)); - sv.s = std::to_string(bool_val); - p_pos += sizeof(uint16_t) + sizeof(bool_val); - } else if (col_type == FlatGeobuf::ColumnType_Short) { - sv.type = mvt_sint; - int16_t short_val; - memcpy(&short_val, feature->properties()->data() + p_pos + sizeof(uint16_t), sizeof(short_val)); - sv.s = std::to_string(short_val); - p_pos += sizeof(uint16_t) + sizeof(short_val); - } else if (col_type == FlatGeobuf::ColumnType_UShort) { - sv.type = mvt_uint; - uint16_t ushort_val; - memcpy(&ushort_val, feature->properties()->data() + p_pos + sizeof(uint16_t), sizeof(ushort_val)); - sv.s = std::to_string(ushort_val); - p_pos += sizeof(uint16_t) + sizeof(ushort_val); - } else if (col_type == FlatGeobuf::ColumnType_Int) { - sv.type = mvt_sint; - int32_t int_val; - memcpy(&int_val, feature->properties()->data() + p_pos + sizeof(uint16_t), sizeof(int_val)); - sv.s = std::to_string(int_val); - p_pos += sizeof(uint16_t) + sizeof(int_val); - } else if (col_type == FlatGeobuf::ColumnType_UInt) { - sv.type = mvt_uint; - uint32_t uint_val; - memcpy(&uint_val, feature->properties()->data() + p_pos + sizeof(uint16_t), sizeof(uint_val)); - sv.s = std::to_string(uint_val); - p_pos += sizeof(uint16_t) + sizeof(uint_val); - } else if (col_type == FlatGeobuf::ColumnType_Long) { - sv.type = mvt_sint; - int64_t long_val; - memcpy(&long_val, feature->properties()->data() + p_pos + sizeof(uint16_t), sizeof(long_val)); - sv.s = std::to_string(long_val); - p_pos += sizeof(uint16_t) + sizeof(long_val); - } else if (col_type == FlatGeobuf::ColumnType_ULong) { - sv.type = mvt_uint; - int64_t ulong_val; - memcpy(&ulong_val, feature->properties()->data() + p_pos + sizeof(uint16_t), sizeof(ulong_val)); - sv.s = std::to_string(ulong_val); - p_pos += sizeof(uint16_t) + sizeof(ulong_val); - } else if (col_type == FlatGeobuf::ColumnType_Float) { - sv.type = mvt_float; - float float_val; - memcpy(&float_val, feature->properties()->data() + p_pos + sizeof(uint16_t), sizeof(float_val)); - sv.s = milo::dtoa_milo(float_val); - p_pos += sizeof(uint16_t) + sizeof(float_val); - } else if (col_type == FlatGeobuf::ColumnType_Double) { - sv.type = mvt_double; - double double_val; - memcpy(&double_val, feature->properties()->data() + p_pos + sizeof(uint16_t), sizeof(double_val)); - sv.s = milo::dtoa_milo(double_val); - p_pos += sizeof(uint16_t) + sizeof(double_val); - } else if (col_type == FlatGeobuf::ColumnType_String || col_type == FlatGeobuf::ColumnType_Json || col_type == FlatGeobuf::ColumnType_DateTime) { - sv.type = mvt_string; - uint32_t val_len; - memcpy(&val_len, feature->properties()->data() + p_pos + sizeof(uint16_t), sizeof(val_len)); - std::string s{reinterpret_cast(feature->properties()->data() + p_pos + sizeof(uint16_t) + sizeof(uint32_t)), val_len}; - sv.s = s; - p_pos += sizeof(uint16_t) + sizeof(uint32_t) + val_len; - } else { - // Binary is not representable in MVT - fprintf(stderr, "flatgeobuf has unsupported column type %u\n", (unsigned int) col_type); - exit(EXIT_IMPOSSIBLE); + serial_val sv; + if (col_type == FlatGeobuf::ColumnType_Byte) { + sv.type = mvt_sint; + int8_t byte_val; + memcpy(&byte_val, feature->properties()->data() + p_pos + sizeof(uint16_t), sizeof(byte_val)); + sv.s = std::to_string(byte_val); + p_pos += sizeof(uint16_t) + sizeof(byte_val); + } else if (col_type == FlatGeobuf::ColumnType_UByte) { + sv.type = mvt_uint; + uint8_t ubyte_val; + memcpy(&ubyte_val, feature->properties()->data() + p_pos + sizeof(uint16_t), sizeof(ubyte_val)); + sv.s = std::to_string(ubyte_val); + p_pos += sizeof(uint16_t) + sizeof(ubyte_val); + } else if (col_type == FlatGeobuf::ColumnType_Bool) { + sv.type = mvt_bool; + uint8_t bool_val; + memcpy(&bool_val, feature->properties()->data() + p_pos + sizeof(uint16_t), sizeof(bool_val)); + sv.s = std::to_string(bool_val); + p_pos += sizeof(uint16_t) + sizeof(bool_val); + } else if (col_type == FlatGeobuf::ColumnType_Short) { + sv.type = mvt_sint; + int16_t short_val; + memcpy(&short_val, feature->properties()->data() + p_pos + sizeof(uint16_t), sizeof(short_val)); + sv.s = std::to_string(short_val); + p_pos += sizeof(uint16_t) + sizeof(short_val); + } else if (col_type == FlatGeobuf::ColumnType_UShort) { + sv.type = mvt_uint; + uint16_t ushort_val; + memcpy(&ushort_val, feature->properties()->data() + p_pos + sizeof(uint16_t), sizeof(ushort_val)); + sv.s = std::to_string(ushort_val); + p_pos += sizeof(uint16_t) + sizeof(ushort_val); + } else if (col_type == FlatGeobuf::ColumnType_Int) { + sv.type = mvt_sint; + int32_t int_val; + memcpy(&int_val, feature->properties()->data() + p_pos + sizeof(uint16_t), sizeof(int_val)); + sv.s = std::to_string(int_val); + p_pos += sizeof(uint16_t) + sizeof(int_val); + } else if (col_type == FlatGeobuf::ColumnType_UInt) { + sv.type = mvt_uint; + uint32_t uint_val; + memcpy(&uint_val, feature->properties()->data() + p_pos + sizeof(uint16_t), sizeof(uint_val)); + sv.s = std::to_string(uint_val); + p_pos += sizeof(uint16_t) + sizeof(uint_val); + } else if (col_type == FlatGeobuf::ColumnType_Long) { + sv.type = mvt_sint; + int64_t long_val; + memcpy(&long_val, feature->properties()->data() + p_pos + sizeof(uint16_t), sizeof(long_val)); + sv.s = std::to_string(long_val); + p_pos += sizeof(uint16_t) + sizeof(long_val); + } else if (col_type == FlatGeobuf::ColumnType_ULong) { + sv.type = mvt_uint; + int64_t ulong_val; + memcpy(&ulong_val, feature->properties()->data() + p_pos + sizeof(uint16_t), sizeof(ulong_val)); + sv.s = std::to_string(ulong_val); + p_pos += sizeof(uint16_t) + sizeof(ulong_val); + } else if (col_type == FlatGeobuf::ColumnType_Float) { + sv.type = mvt_float; + float float_val; + memcpy(&float_val, feature->properties()->data() + p_pos + sizeof(uint16_t), sizeof(float_val)); + sv.s = milo::dtoa_milo(float_val); + p_pos += sizeof(uint16_t) + sizeof(float_val); + } else if (col_type == FlatGeobuf::ColumnType_Double) { + sv.type = mvt_double; + double double_val; + memcpy(&double_val, feature->properties()->data() + p_pos + sizeof(uint16_t), sizeof(double_val)); + sv.s = milo::dtoa_milo(double_val); + p_pos += sizeof(uint16_t) + sizeof(double_val); + } else if (col_type == FlatGeobuf::ColumnType_String || col_type == FlatGeobuf::ColumnType_Json || col_type == FlatGeobuf::ColumnType_DateTime) { + sv.type = mvt_string; + uint32_t val_len; + memcpy(&val_len, feature->properties()->data() + p_pos + sizeof(uint16_t), sizeof(val_len)); + std::string s{reinterpret_cast(feature->properties()->data() + p_pos + sizeof(uint16_t) + sizeof(uint32_t)), val_len}; + sv.s = s; + p_pos += sizeof(uint16_t) + sizeof(uint32_t) + val_len; + } else { + // Binary is not representable in MVT + fprintf(stderr, "flatgeobuf has unsupported column type %u\n", (unsigned int) col_type); + exit(EXIT_IMPOSSIBLE); + } + full_keys.push_back(h_column_names[col_idx]); + full_values.push_back(sv); } - full_keys.push_back(h_column_names[col_idx]); - full_values.push_back(sv); } sf.full_keys = full_keys;