Shapefile main file: C++11/STL parsing library

File extension

shp

KS implementation details

License: CC0-1.0

References

This page hosts a formal specification of Shapefile main file using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.

Usage

Runtime library

All parsing code for C++11/STL generated by Kaitai Struct depends on the C++/STL runtime library. You have to install it before you can parse data.

For C++, the easiest way is to clone the runtime library sources and build them along with your project.

Code

Using Kaitai Struct in C++/STL usually consists of 3 steps.

  1. We need to create an STL input stream (std::istream). One can open local file for that, or use existing std::string or char* buffer.
    #include <fstream>
    
    std::ifstream is("path/to/local/file.shp", std::ifstream::binary);
    
    #include <sstream>
    
    std::istringstream is(str);
    
    #include <sstream>
    
    const char buf[] = { ... };
    std::string str(buf, sizeof buf);
    std::istringstream is(str);
    
  2. We need to wrap our input stream into Kaitai stream:
    #include "kaitai/kaitaistream.h"
    
    kaitai::kstream ks(&is);
    
  3. And finally, we can invoke the parsing:
    shapefile_main_t data(&ks);
    

After that, one can get various attributes from the structure by invoking getter methods like:

data.records() // => the size of this section of the file in bytes must equal (header.file_length * 2) - 100

C++11/STL source code to parse Shapefile main file

shapefile_main.h

#pragma once

// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild

#include "kaitai/kaitaistruct.h"
#include <stdint.h>
#include <memory>
#include <vector>

#if KAITAI_STRUCT_VERSION < 9000L
#error "Incompatible Kaitai Struct C++/STL API: version 0.9 or later is required"
#endif

class shapefile_main_t : public kaitai::kstruct {

public:
    class multi_point_m_t;
    class bounding_box_x_y_z_m_t;
    class point_t;
    class polygon_t;
    class bounds_min_max_t;
    class poly_line_t;
    class multi_point_z_t;
    class poly_line_z_t;
    class polygon_z_t;
    class bounding_box_x_y_t;
    class point_m_t;
    class polygon_m_t;
    class record_header_t;
    class multi_point_t;
    class file_header_t;
    class point_z_t;
    class record_t;
    class record_contents_t;
    class multi_patch_t;
    class poly_line_m_t;

    enum shape_type_t {
        SHAPE_TYPE_NULL_SHAPE = 0,
        SHAPE_TYPE_POINT = 1,
        SHAPE_TYPE_POLY_LINE = 3,
        SHAPE_TYPE_POLYGON = 5,
        SHAPE_TYPE_MULTI_POINT = 8,
        SHAPE_TYPE_POINT_Z = 11,
        SHAPE_TYPE_POLY_LINE_Z = 13,
        SHAPE_TYPE_POLYGON_Z = 15,
        SHAPE_TYPE_MULTI_POINT_Z = 18,
        SHAPE_TYPE_POINT_M = 21,
        SHAPE_TYPE_POLY_LINE_M = 23,
        SHAPE_TYPE_POLYGON_M = 25,
        SHAPE_TYPE_MULTI_POINT_M = 28,
        SHAPE_TYPE_MULTI_PATCH = 31
    };

    enum part_type_t {
        PART_TYPE_TRIANGLE_STRIP = 0,
        PART_TYPE_TRIANGLE_FAN = 1,
        PART_TYPE_OUTER_RING = 2,
        PART_TYPE_INNER_RING = 3,
        PART_TYPE_FIRST_RING = 4,
        PART_TYPE_RING = 5
    };

    shapefile_main_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = nullptr, shapefile_main_t* p__root = nullptr);

private:
    void _read();
    void _clean_up();

public:
    ~shapefile_main_t();

    class multi_point_m_t : public kaitai::kstruct {

    public:

        multi_point_m_t(kaitai::kstream* p__io, shapefile_main_t::record_contents_t* p__parent = nullptr, shapefile_main_t* p__root = nullptr);

    private:
        void _read();
        void _clean_up();

    public:
        ~multi_point_m_t();

    private:
        std::unique_ptr<bounding_box_x_y_t> m_bounding_box;
        int32_t m_number_of_points;
        std::unique_ptr<std::vector<std::unique_ptr<point_t>>> m_points;
        std::unique_ptr<bounds_min_max_t> m_m_range;
        std::unique_ptr<std::vector<double>> m_m_values;
        shapefile_main_t* m__root;
        shapefile_main_t::record_contents_t* m__parent;

    public:
        bounding_box_x_y_t* bounding_box() const { return m_bounding_box.get(); }
        int32_t number_of_points() const { return m_number_of_points; }
        std::vector<std::unique_ptr<point_t>>* points() const { return m_points.get(); }
        bounds_min_max_t* m_range() const { return m_m_range.get(); }
        std::vector<double>* m_values() const { return m_m_values.get(); }
        shapefile_main_t* _root() const { return m__root; }
        shapefile_main_t::record_contents_t* _parent() const { return m__parent; }
    };

    class bounding_box_x_y_z_m_t : public kaitai::kstruct {

    public:

        bounding_box_x_y_z_m_t(kaitai::kstream* p__io, shapefile_main_t::file_header_t* p__parent = nullptr, shapefile_main_t* p__root = nullptr);

    private:
        void _read();
        void _clean_up();

    public:
        ~bounding_box_x_y_z_m_t();

    private:
        std::unique_ptr<bounds_min_max_t> m_x;
        std::unique_ptr<bounds_min_max_t> m_y;
        std::unique_ptr<bounds_min_max_t> m_z;
        std::unique_ptr<bounds_min_max_t> m_m;
        shapefile_main_t* m__root;
        shapefile_main_t::file_header_t* m__parent;

    public:
        bounds_min_max_t* x() const { return m_x.get(); }
        bounds_min_max_t* y() const { return m_y.get(); }
        bounds_min_max_t* z() const { return m_z.get(); }
        bounds_min_max_t* m() const { return m_m.get(); }
        shapefile_main_t* _root() const { return m__root; }
        shapefile_main_t::file_header_t* _parent() const { return m__parent; }
    };

    class point_t : public kaitai::kstruct {

    public:

        point_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = nullptr, shapefile_main_t* p__root = nullptr);

    private:
        void _read();
        void _clean_up();

    public:
        ~point_t();

    private:
        double m_x;
        double m_y;
        shapefile_main_t* m__root;
        kaitai::kstruct* m__parent;

    public:
        double x() const { return m_x; }
        double y() const { return m_y; }
        shapefile_main_t* _root() const { return m__root; }
        kaitai::kstruct* _parent() const { return m__parent; }
    };

    class polygon_t : public kaitai::kstruct {

    public:

        polygon_t(kaitai::kstream* p__io, shapefile_main_t::record_contents_t* p__parent = nullptr, shapefile_main_t* p__root = nullptr);

    private:
        void _read();
        void _clean_up();

    public:
        ~polygon_t();

    private:
        std::unique_ptr<bounding_box_x_y_t> m_bounding_box;
        int32_t m_number_of_parts;
        int32_t m_number_of_points;
        std::unique_ptr<std::vector<int32_t>> m_parts;
        std::unique_ptr<std::vector<std::unique_ptr<point_t>>> m_points;
        shapefile_main_t* m__root;
        shapefile_main_t::record_contents_t* m__parent;

    public:
        bounding_box_x_y_t* bounding_box() const { return m_bounding_box.get(); }
        int32_t number_of_parts() const { return m_number_of_parts; }
        int32_t number_of_points() const { return m_number_of_points; }
        std::vector<int32_t>* parts() const { return m_parts.get(); }
        std::vector<std::unique_ptr<point_t>>* points() const { return m_points.get(); }
        shapefile_main_t* _root() const { return m__root; }
        shapefile_main_t::record_contents_t* _parent() const { return m__parent; }
    };

    class bounds_min_max_t : public kaitai::kstruct {

    public:

        bounds_min_max_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = nullptr, shapefile_main_t* p__root = nullptr);

    private:
        void _read();
        void _clean_up();

    public:
        ~bounds_min_max_t();

    private:
        double m_min;
        double m_max;
        shapefile_main_t* m__root;
        kaitai::kstruct* m__parent;

    public:
        double min() const { return m_min; }
        double max() const { return m_max; }
        shapefile_main_t* _root() const { return m__root; }
        kaitai::kstruct* _parent() const { return m__parent; }
    };

    class poly_line_t : public kaitai::kstruct {

    public:

        poly_line_t(kaitai::kstream* p__io, shapefile_main_t::record_contents_t* p__parent = nullptr, shapefile_main_t* p__root = nullptr);

    private:
        void _read();
        void _clean_up();

    public:
        ~poly_line_t();

    private:
        std::unique_ptr<bounding_box_x_y_t> m_bounding_box;
        int32_t m_number_of_parts;
        int32_t m_number_of_points;
        std::unique_ptr<std::vector<int32_t>> m_parts;
        std::unique_ptr<std::vector<std::unique_ptr<point_t>>> m_points;
        shapefile_main_t* m__root;
        shapefile_main_t::record_contents_t* m__parent;

    public:
        bounding_box_x_y_t* bounding_box() const { return m_bounding_box.get(); }
        int32_t number_of_parts() const { return m_number_of_parts; }
        int32_t number_of_points() const { return m_number_of_points; }
        std::vector<int32_t>* parts() const { return m_parts.get(); }
        std::vector<std::unique_ptr<point_t>>* points() const { return m_points.get(); }
        shapefile_main_t* _root() const { return m__root; }
        shapefile_main_t::record_contents_t* _parent() const { return m__parent; }
    };

    class multi_point_z_t : public kaitai::kstruct {

    public:

        multi_point_z_t(kaitai::kstream* p__io, shapefile_main_t::record_contents_t* p__parent = nullptr, shapefile_main_t* p__root = nullptr);

    private:
        void _read();
        void _clean_up();

    public:
        ~multi_point_z_t();

    private:
        std::unique_ptr<bounding_box_x_y_t> m_bounding_box;
        int32_t m_number_of_points;
        std::unique_ptr<std::vector<std::unique_ptr<point_t>>> m_points;
        std::unique_ptr<bounds_min_max_t> m_z_range;
        std::unique_ptr<std::vector<double>> m_z_values;
        std::unique_ptr<bounds_min_max_t> m_m_range;
        std::unique_ptr<std::vector<double>> m_m_values;
        shapefile_main_t* m__root;
        shapefile_main_t::record_contents_t* m__parent;

    public:
        bounding_box_x_y_t* bounding_box() const { return m_bounding_box.get(); }
        int32_t number_of_points() const { return m_number_of_points; }
        std::vector<std::unique_ptr<point_t>>* points() const { return m_points.get(); }
        bounds_min_max_t* z_range() const { return m_z_range.get(); }
        std::vector<double>* z_values() const { return m_z_values.get(); }
        bounds_min_max_t* m_range() const { return m_m_range.get(); }
        std::vector<double>* m_values() const { return m_m_values.get(); }
        shapefile_main_t* _root() const { return m__root; }
        shapefile_main_t::record_contents_t* _parent() const { return m__parent; }
    };

    class poly_line_z_t : public kaitai::kstruct {

    public:

        poly_line_z_t(kaitai::kstream* p__io, shapefile_main_t::record_contents_t* p__parent = nullptr, shapefile_main_t* p__root = nullptr);

    private:
        void _read();
        void _clean_up();

    public:
        ~poly_line_z_t();

    private:
        std::unique_ptr<bounding_box_x_y_t> m_bounding_box;
        int32_t m_number_of_parts;
        int32_t m_number_of_points;
        std::unique_ptr<std::vector<int32_t>> m_parts;
        std::unique_ptr<std::vector<std::unique_ptr<point_t>>> m_points;
        std::unique_ptr<bounds_min_max_t> m_z_range;
        std::unique_ptr<std::vector<double>> m_z_values;
        std::unique_ptr<bounds_min_max_t> m_m_range;
        std::unique_ptr<std::vector<double>> m_m_values;
        shapefile_main_t* m__root;
        shapefile_main_t::record_contents_t* m__parent;

    public:
        bounding_box_x_y_t* bounding_box() const { return m_bounding_box.get(); }
        int32_t number_of_parts() const { return m_number_of_parts; }
        int32_t number_of_points() const { return m_number_of_points; }
        std::vector<int32_t>* parts() const { return m_parts.get(); }
        std::vector<std::unique_ptr<point_t>>* points() const { return m_points.get(); }
        bounds_min_max_t* z_range() const { return m_z_range.get(); }
        std::vector<double>* z_values() const { return m_z_values.get(); }
        bounds_min_max_t* m_range() const { return m_m_range.get(); }
        std::vector<double>* m_values() const { return m_m_values.get(); }
        shapefile_main_t* _root() const { return m__root; }
        shapefile_main_t::record_contents_t* _parent() const { return m__parent; }
    };

    class polygon_z_t : public kaitai::kstruct {

    public:

        polygon_z_t(kaitai::kstream* p__io, shapefile_main_t::record_contents_t* p__parent = nullptr, shapefile_main_t* p__root = nullptr);

    private:
        void _read();
        void _clean_up();

    public:
        ~polygon_z_t();

    private:
        std::unique_ptr<bounding_box_x_y_t> m_bounding_box;
        int32_t m_number_of_parts;
        int32_t m_number_of_points;
        std::unique_ptr<std::vector<int32_t>> m_parts;
        std::unique_ptr<std::vector<std::unique_ptr<point_t>>> m_points;
        std::unique_ptr<bounds_min_max_t> m_z_range;
        std::unique_ptr<std::vector<double>> m_z_values;
        std::unique_ptr<bounds_min_max_t> m_m_range;
        std::unique_ptr<std::vector<double>> m_m_values;
        shapefile_main_t* m__root;
        shapefile_main_t::record_contents_t* m__parent;

    public:
        bounding_box_x_y_t* bounding_box() const { return m_bounding_box.get(); }
        int32_t number_of_parts() const { return m_number_of_parts; }
        int32_t number_of_points() const { return m_number_of_points; }
        std::vector<int32_t>* parts() const { return m_parts.get(); }
        std::vector<std::unique_ptr<point_t>>* points() const { return m_points.get(); }
        bounds_min_max_t* z_range() const { return m_z_range.get(); }
        std::vector<double>* z_values() const { return m_z_values.get(); }
        bounds_min_max_t* m_range() const { return m_m_range.get(); }
        std::vector<double>* m_values() const { return m_m_values.get(); }
        shapefile_main_t* _root() const { return m__root; }
        shapefile_main_t::record_contents_t* _parent() const { return m__parent; }
    };

    class bounding_box_x_y_t : public kaitai::kstruct {

    public:

        bounding_box_x_y_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = nullptr, shapefile_main_t* p__root = nullptr);

    private:
        void _read();
        void _clean_up();

    public:
        ~bounding_box_x_y_t();

    private:
        std::unique_ptr<bounds_min_max_t> m_x;
        std::unique_ptr<bounds_min_max_t> m_y;
        shapefile_main_t* m__root;
        kaitai::kstruct* m__parent;

    public:
        bounds_min_max_t* x() const { return m_x.get(); }
        bounds_min_max_t* y() const { return m_y.get(); }
        shapefile_main_t* _root() const { return m__root; }
        kaitai::kstruct* _parent() const { return m__parent; }
    };

    class point_m_t : public kaitai::kstruct {

    public:

        point_m_t(kaitai::kstream* p__io, shapefile_main_t::record_contents_t* p__parent = nullptr, shapefile_main_t* p__root = nullptr);

    private:
        void _read();
        void _clean_up();

    public:
        ~point_m_t();

    private:
        double m_x;
        double m_y;
        double m_m;
        shapefile_main_t* m__root;
        shapefile_main_t::record_contents_t* m__parent;

    public:
        double x() const { return m_x; }
        double y() const { return m_y; }
        double m() const { return m_m; }
        shapefile_main_t* _root() const { return m__root; }
        shapefile_main_t::record_contents_t* _parent() const { return m__parent; }
    };

    class polygon_m_t : public kaitai::kstruct {

    public:

        polygon_m_t(kaitai::kstream* p__io, shapefile_main_t::record_contents_t* p__parent = nullptr, shapefile_main_t* p__root = nullptr);

    private:
        void _read();
        void _clean_up();

    public:
        ~polygon_m_t();

    private:
        std::unique_ptr<bounding_box_x_y_t> m_bounding_box;
        int32_t m_number_of_parts;
        int32_t m_number_of_points;
        std::unique_ptr<std::vector<int32_t>> m_parts;
        std::unique_ptr<std::vector<std::unique_ptr<point_t>>> m_points;
        std::unique_ptr<bounds_min_max_t> m_m_range;
        std::unique_ptr<std::vector<double>> m_m_values;
        shapefile_main_t* m__root;
        shapefile_main_t::record_contents_t* m__parent;

    public:
        bounding_box_x_y_t* bounding_box() const { return m_bounding_box.get(); }
        int32_t number_of_parts() const { return m_number_of_parts; }
        int32_t number_of_points() const { return m_number_of_points; }
        std::vector<int32_t>* parts() const { return m_parts.get(); }
        std::vector<std::unique_ptr<point_t>>* points() const { return m_points.get(); }
        bounds_min_max_t* m_range() const { return m_m_range.get(); }
        std::vector<double>* m_values() const { return m_m_values.get(); }
        shapefile_main_t* _root() const { return m__root; }
        shapefile_main_t::record_contents_t* _parent() const { return m__parent; }
    };

    class record_header_t : public kaitai::kstruct {

    public:

        record_header_t(kaitai::kstream* p__io, shapefile_main_t::record_t* p__parent = nullptr, shapefile_main_t* p__root = nullptr);

    private:
        void _read();
        void _clean_up();

    public:
        ~record_header_t();

    private:
        int32_t m_record_number;
        int32_t m_content_length;
        shapefile_main_t* m__root;
        shapefile_main_t::record_t* m__parent;

    public:
        int32_t record_number() const { return m_record_number; }
        int32_t content_length() const { return m_content_length; }
        shapefile_main_t* _root() const { return m__root; }
        shapefile_main_t::record_t* _parent() const { return m__parent; }
    };

    class multi_point_t : public kaitai::kstruct {

    public:

        multi_point_t(kaitai::kstream* p__io, shapefile_main_t::record_contents_t* p__parent = nullptr, shapefile_main_t* p__root = nullptr);

    private:
        void _read();
        void _clean_up();

    public:
        ~multi_point_t();

    private:
        std::unique_ptr<bounding_box_x_y_t> m_bounding_box;
        int32_t m_number_of_points;
        std::unique_ptr<std::vector<std::unique_ptr<point_t>>> m_points;
        shapefile_main_t* m__root;
        shapefile_main_t::record_contents_t* m__parent;

    public:
        bounding_box_x_y_t* bounding_box() const { return m_bounding_box.get(); }
        int32_t number_of_points() const { return m_number_of_points; }
        std::vector<std::unique_ptr<point_t>>* points() const { return m_points.get(); }
        shapefile_main_t* _root() const { return m__root; }
        shapefile_main_t::record_contents_t* _parent() const { return m__parent; }
    };

    class file_header_t : public kaitai::kstruct {

    public:

        file_header_t(kaitai::kstream* p__io, shapefile_main_t* p__parent = nullptr, shapefile_main_t* p__root = nullptr);

    private:
        void _read();
        void _clean_up();

    public:
        ~file_header_t();

    private:
        std::string m_file_code;
        std::string m_unused_field_1;
        std::string m_unused_field_2;
        std::string m_unused_field_3;
        std::string m_unused_field_4;
        std::string m_unused_field_5;
        int32_t m_file_length;
        std::string m_version;
        shape_type_t m_shape_type;
        std::unique_ptr<bounding_box_x_y_z_m_t> m_bounding_box;
        shapefile_main_t* m__root;
        shapefile_main_t* m__parent;

    public:

        /**
         * corresponds to s4be value of 9994
         */
        std::string file_code() const { return m_file_code; }
        std::string unused_field_1() const { return m_unused_field_1; }
        std::string unused_field_2() const { return m_unused_field_2; }
        std::string unused_field_3() const { return m_unused_field_3; }
        std::string unused_field_4() const { return m_unused_field_4; }
        std::string unused_field_5() const { return m_unused_field_5; }
        int32_t file_length() const { return m_file_length; }

        /**
         * corresponds to s4le value of 1000
         */
        std::string version() const { return m_version; }
        shape_type_t shape_type() const { return m_shape_type; }
        bounding_box_x_y_z_m_t* bounding_box() const { return m_bounding_box.get(); }
        shapefile_main_t* _root() const { return m__root; }
        shapefile_main_t* _parent() const { return m__parent; }
    };

    class point_z_t : public kaitai::kstruct {

    public:

        point_z_t(kaitai::kstream* p__io, shapefile_main_t::record_contents_t* p__parent = nullptr, shapefile_main_t* p__root = nullptr);

    private:
        void _read();
        void _clean_up();

    public:
        ~point_z_t();

    private:
        double m_x;
        double m_y;
        double m_z;
        double m_m;
        shapefile_main_t* m__root;
        shapefile_main_t::record_contents_t* m__parent;

    public:
        double x() const { return m_x; }
        double y() const { return m_y; }
        double z() const { return m_z; }
        double m() const { return m_m; }
        shapefile_main_t* _root() const { return m__root; }
        shapefile_main_t::record_contents_t* _parent() const { return m__parent; }
    };

    class record_t : public kaitai::kstruct {

    public:

        record_t(kaitai::kstream* p__io, shapefile_main_t* p__parent = nullptr, shapefile_main_t* p__root = nullptr);

    private:
        void _read();
        void _clean_up();

    public:
        ~record_t();

    private:
        std::unique_ptr<record_header_t> m_header;
        std::unique_ptr<record_contents_t> m_contents;
        shapefile_main_t* m__root;
        shapefile_main_t* m__parent;

    public:
        record_header_t* header() const { return m_header.get(); }

        /**
         * the size of this contents section in bytes must equal header.content_length * 2
         */
        record_contents_t* contents() const { return m_contents.get(); }
        shapefile_main_t* _root() const { return m__root; }
        shapefile_main_t* _parent() const { return m__parent; }
    };

    class record_contents_t : public kaitai::kstruct {

    public:

        record_contents_t(kaitai::kstream* p__io, shapefile_main_t::record_t* p__parent = nullptr, shapefile_main_t* p__root = nullptr);

    private:
        void _read();
        void _clean_up();

    public:
        ~record_contents_t();

    private:
        shape_type_t m_shape_type;
        std::unique_ptr<kaitai::kstruct> m_shape_parameters;
        bool n_shape_parameters;

    public:
        bool _is_null_shape_parameters() { shape_parameters(); return n_shape_parameters; };

    private:
        shapefile_main_t* m__root;
        shapefile_main_t::record_t* m__parent;

    public:
        shape_type_t shape_type() const { return m_shape_type; }
        kaitai::kstruct* shape_parameters() const { return m_shape_parameters.get(); }
        shapefile_main_t* _root() const { return m__root; }
        shapefile_main_t::record_t* _parent() const { return m__parent; }
    };

    class multi_patch_t : public kaitai::kstruct {

    public:

        multi_patch_t(kaitai::kstream* p__io, shapefile_main_t::record_contents_t* p__parent = nullptr, shapefile_main_t* p__root = nullptr);

    private:
        void _read();
        void _clean_up();

    public:
        ~multi_patch_t();

    private:
        std::unique_ptr<bounding_box_x_y_t> m_bounding_box;
        int32_t m_number_of_parts;
        int32_t m_number_of_points;
        std::unique_ptr<std::vector<int32_t>> m_parts;
        std::unique_ptr<std::vector<part_type_t>> m_part_types;
        std::unique_ptr<std::vector<std::unique_ptr<point_t>>> m_points;
        std::unique_ptr<bounds_min_max_t> m_z_range;
        std::unique_ptr<std::vector<double>> m_z_values;
        std::unique_ptr<bounds_min_max_t> m_m_range;
        std::unique_ptr<std::vector<double>> m_m_values;
        shapefile_main_t* m__root;
        shapefile_main_t::record_contents_t* m__parent;

    public:
        bounding_box_x_y_t* bounding_box() const { return m_bounding_box.get(); }
        int32_t number_of_parts() const { return m_number_of_parts; }
        int32_t number_of_points() const { return m_number_of_points; }
        std::vector<int32_t>* parts() const { return m_parts.get(); }
        std::vector<part_type_t>* part_types() const { return m_part_types.get(); }
        std::vector<std::unique_ptr<point_t>>* points() const { return m_points.get(); }
        bounds_min_max_t* z_range() const { return m_z_range.get(); }
        std::vector<double>* z_values() const { return m_z_values.get(); }
        bounds_min_max_t* m_range() const { return m_m_range.get(); }
        std::vector<double>* m_values() const { return m_m_values.get(); }
        shapefile_main_t* _root() const { return m__root; }
        shapefile_main_t::record_contents_t* _parent() const { return m__parent; }
    };

    class poly_line_m_t : public kaitai::kstruct {

    public:

        poly_line_m_t(kaitai::kstream* p__io, shapefile_main_t::record_contents_t* p__parent = nullptr, shapefile_main_t* p__root = nullptr);

    private:
        void _read();
        void _clean_up();

    public:
        ~poly_line_m_t();

    private:
        std::unique_ptr<bounding_box_x_y_t> m_bounding_box;
        int32_t m_number_of_parts;
        int32_t m_number_of_points;
        std::unique_ptr<std::vector<int32_t>> m_parts;
        std::unique_ptr<std::vector<std::unique_ptr<point_t>>> m_points;
        std::unique_ptr<bounds_min_max_t> m_m_range;
        std::unique_ptr<std::vector<double>> m_m_values;
        shapefile_main_t* m__root;
        shapefile_main_t::record_contents_t* m__parent;

    public:
        bounding_box_x_y_t* bounding_box() const { return m_bounding_box.get(); }
        int32_t number_of_parts() const { return m_number_of_parts; }
        int32_t number_of_points() const { return m_number_of_points; }
        std::vector<int32_t>* parts() const { return m_parts.get(); }
        std::vector<std::unique_ptr<point_t>>* points() const { return m_points.get(); }
        bounds_min_max_t* m_range() const { return m_m_range.get(); }
        std::vector<double>* m_values() const { return m_m_values.get(); }
        shapefile_main_t* _root() const { return m__root; }
        shapefile_main_t::record_contents_t* _parent() const { return m__parent; }
    };

private:
    std::unique_ptr<file_header_t> m_header;
    std::unique_ptr<std::vector<std::unique_ptr<record_t>>> m_records;
    shapefile_main_t* m__root;
    kaitai::kstruct* m__parent;

public:
    file_header_t* header() const { return m_header.get(); }

    /**
     * the size of this section of the file in bytes must equal (header.file_length * 2) - 100
     */
    std::vector<std::unique_ptr<record_t>>* records() const { return m_records.get(); }
    shapefile_main_t* _root() const { return m__root; }
    kaitai::kstruct* _parent() const { return m__parent; }
};

shapefile_main.cpp

// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild

#include "shapefile_main.h"
#include "kaitai/exceptions.h"

shapefile_main_t::shapefile_main_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, shapefile_main_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = this;
    m_header = nullptr;
    m_records = nullptr;
    _read();
}

void shapefile_main_t::_read() {
    m_header = std::unique_ptr<file_header_t>(new file_header_t(m__io, this, m__root));
    m_records = std::unique_ptr<std::vector<std::unique_ptr<record_t>>>(new std::vector<std::unique_ptr<record_t>>());
    {
        int i = 0;
        while (!m__io->is_eof()) {
            m_records->push_back(std::move(std::unique_ptr<record_t>(new record_t(m__io, this, m__root))));
            i++;
        }
    }
}

shapefile_main_t::~shapefile_main_t() {
    _clean_up();
}

void shapefile_main_t::_clean_up() {
}

shapefile_main_t::multi_point_m_t::multi_point_m_t(kaitai::kstream* p__io, shapefile_main_t::record_contents_t* p__parent, shapefile_main_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    m_bounding_box = nullptr;
    m_points = nullptr;
    m_m_range = nullptr;
    m_m_values = nullptr;
    _read();
}

void shapefile_main_t::multi_point_m_t::_read() {
    m_bounding_box = std::unique_ptr<bounding_box_x_y_t>(new bounding_box_x_y_t(m__io, this, m__root));
    m_number_of_points = m__io->read_s4le();
    m_points = std::unique_ptr<std::vector<std::unique_ptr<point_t>>>(new std::vector<std::unique_ptr<point_t>>());
    const int l_points = number_of_points();
    for (int i = 0; i < l_points; i++) {
        m_points->push_back(std::move(std::unique_ptr<point_t>(new point_t(m__io, this, m__root))));
    }
    m_m_range = std::unique_ptr<bounds_min_max_t>(new bounds_min_max_t(m__io, this, m__root));
    m_m_values = std::unique_ptr<std::vector<double>>(new std::vector<double>());
    const int l_m_values = number_of_points();
    for (int i = 0; i < l_m_values; i++) {
        m_m_values->push_back(std::move(m__io->read_f8le()));
    }
}

shapefile_main_t::multi_point_m_t::~multi_point_m_t() {
    _clean_up();
}

void shapefile_main_t::multi_point_m_t::_clean_up() {
}

shapefile_main_t::bounding_box_x_y_z_m_t::bounding_box_x_y_z_m_t(kaitai::kstream* p__io, shapefile_main_t::file_header_t* p__parent, shapefile_main_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    m_x = nullptr;
    m_y = nullptr;
    m_z = nullptr;
    m_m = nullptr;
    _read();
}

void shapefile_main_t::bounding_box_x_y_z_m_t::_read() {
    m_x = std::unique_ptr<bounds_min_max_t>(new bounds_min_max_t(m__io, this, m__root));
    m_y = std::unique_ptr<bounds_min_max_t>(new bounds_min_max_t(m__io, this, m__root));
    m_z = std::unique_ptr<bounds_min_max_t>(new bounds_min_max_t(m__io, this, m__root));
    m_m = std::unique_ptr<bounds_min_max_t>(new bounds_min_max_t(m__io, this, m__root));
}

shapefile_main_t::bounding_box_x_y_z_m_t::~bounding_box_x_y_z_m_t() {
    _clean_up();
}

void shapefile_main_t::bounding_box_x_y_z_m_t::_clean_up() {
}

shapefile_main_t::point_t::point_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, shapefile_main_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    _read();
}

void shapefile_main_t::point_t::_read() {
    m_x = m__io->read_f8le();
    m_y = m__io->read_f8le();
}

shapefile_main_t::point_t::~point_t() {
    _clean_up();
}

void shapefile_main_t::point_t::_clean_up() {
}

shapefile_main_t::polygon_t::polygon_t(kaitai::kstream* p__io, shapefile_main_t::record_contents_t* p__parent, shapefile_main_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    m_bounding_box = nullptr;
    m_parts = nullptr;
    m_points = nullptr;
    _read();
}

void shapefile_main_t::polygon_t::_read() {
    m_bounding_box = std::unique_ptr<bounding_box_x_y_t>(new bounding_box_x_y_t(m__io, this, m__root));
    m_number_of_parts = m__io->read_s4le();
    m_number_of_points = m__io->read_s4le();
    m_parts = std::unique_ptr<std::vector<int32_t>>(new std::vector<int32_t>());
    const int l_parts = number_of_parts();
    for (int i = 0; i < l_parts; i++) {
        m_parts->push_back(std::move(m__io->read_s4le()));
    }
    m_points = std::unique_ptr<std::vector<std::unique_ptr<point_t>>>(new std::vector<std::unique_ptr<point_t>>());
    const int l_points = number_of_points();
    for (int i = 0; i < l_points; i++) {
        m_points->push_back(std::move(std::unique_ptr<point_t>(new point_t(m__io, this, m__root))));
    }
}

shapefile_main_t::polygon_t::~polygon_t() {
    _clean_up();
}

void shapefile_main_t::polygon_t::_clean_up() {
}

shapefile_main_t::bounds_min_max_t::bounds_min_max_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, shapefile_main_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    _read();
}

void shapefile_main_t::bounds_min_max_t::_read() {
    m_min = m__io->read_f8le();
    m_max = m__io->read_f8le();
}

shapefile_main_t::bounds_min_max_t::~bounds_min_max_t() {
    _clean_up();
}

void shapefile_main_t::bounds_min_max_t::_clean_up() {
}

shapefile_main_t::poly_line_t::poly_line_t(kaitai::kstream* p__io, shapefile_main_t::record_contents_t* p__parent, shapefile_main_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    m_bounding_box = nullptr;
    m_parts = nullptr;
    m_points = nullptr;
    _read();
}

void shapefile_main_t::poly_line_t::_read() {
    m_bounding_box = std::unique_ptr<bounding_box_x_y_t>(new bounding_box_x_y_t(m__io, this, m__root));
    m_number_of_parts = m__io->read_s4le();
    m_number_of_points = m__io->read_s4le();
    m_parts = std::unique_ptr<std::vector<int32_t>>(new std::vector<int32_t>());
    const int l_parts = number_of_parts();
    for (int i = 0; i < l_parts; i++) {
        m_parts->push_back(std::move(m__io->read_s4le()));
    }
    m_points = std::unique_ptr<std::vector<std::unique_ptr<point_t>>>(new std::vector<std::unique_ptr<point_t>>());
    const int l_points = number_of_points();
    for (int i = 0; i < l_points; i++) {
        m_points->push_back(std::move(std::unique_ptr<point_t>(new point_t(m__io, this, m__root))));
    }
}

shapefile_main_t::poly_line_t::~poly_line_t() {
    _clean_up();
}

void shapefile_main_t::poly_line_t::_clean_up() {
}

shapefile_main_t::multi_point_z_t::multi_point_z_t(kaitai::kstream* p__io, shapefile_main_t::record_contents_t* p__parent, shapefile_main_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    m_bounding_box = nullptr;
    m_points = nullptr;
    m_z_range = nullptr;
    m_z_values = nullptr;
    m_m_range = nullptr;
    m_m_values = nullptr;
    _read();
}

void shapefile_main_t::multi_point_z_t::_read() {
    m_bounding_box = std::unique_ptr<bounding_box_x_y_t>(new bounding_box_x_y_t(m__io, this, m__root));
    m_number_of_points = m__io->read_s4le();
    m_points = std::unique_ptr<std::vector<std::unique_ptr<point_t>>>(new std::vector<std::unique_ptr<point_t>>());
    const int l_points = number_of_points();
    for (int i = 0; i < l_points; i++) {
        m_points->push_back(std::move(std::unique_ptr<point_t>(new point_t(m__io, this, m__root))));
    }
    m_z_range = std::unique_ptr<bounds_min_max_t>(new bounds_min_max_t(m__io, this, m__root));
    m_z_values = std::unique_ptr<std::vector<double>>(new std::vector<double>());
    const int l_z_values = number_of_points();
    for (int i = 0; i < l_z_values; i++) {
        m_z_values->push_back(std::move(m__io->read_f8le()));
    }
    m_m_range = std::unique_ptr<bounds_min_max_t>(new bounds_min_max_t(m__io, this, m__root));
    m_m_values = std::unique_ptr<std::vector<double>>(new std::vector<double>());
    const int l_m_values = number_of_points();
    for (int i = 0; i < l_m_values; i++) {
        m_m_values->push_back(std::move(m__io->read_f8le()));
    }
}

shapefile_main_t::multi_point_z_t::~multi_point_z_t() {
    _clean_up();
}

void shapefile_main_t::multi_point_z_t::_clean_up() {
}

shapefile_main_t::poly_line_z_t::poly_line_z_t(kaitai::kstream* p__io, shapefile_main_t::record_contents_t* p__parent, shapefile_main_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    m_bounding_box = nullptr;
    m_parts = nullptr;
    m_points = nullptr;
    m_z_range = nullptr;
    m_z_values = nullptr;
    m_m_range = nullptr;
    m_m_values = nullptr;
    _read();
}

void shapefile_main_t::poly_line_z_t::_read() {
    m_bounding_box = std::unique_ptr<bounding_box_x_y_t>(new bounding_box_x_y_t(m__io, this, m__root));
    m_number_of_parts = m__io->read_s4le();
    m_number_of_points = m__io->read_s4le();
    m_parts = std::unique_ptr<std::vector<int32_t>>(new std::vector<int32_t>());
    const int l_parts = number_of_parts();
    for (int i = 0; i < l_parts; i++) {
        m_parts->push_back(std::move(m__io->read_s4le()));
    }
    m_points = std::unique_ptr<std::vector<std::unique_ptr<point_t>>>(new std::vector<std::unique_ptr<point_t>>());
    const int l_points = number_of_points();
    for (int i = 0; i < l_points; i++) {
        m_points->push_back(std::move(std::unique_ptr<point_t>(new point_t(m__io, this, m__root))));
    }
    m_z_range = std::unique_ptr<bounds_min_max_t>(new bounds_min_max_t(m__io, this, m__root));
    m_z_values = std::unique_ptr<std::vector<double>>(new std::vector<double>());
    const int l_z_values = number_of_points();
    for (int i = 0; i < l_z_values; i++) {
        m_z_values->push_back(std::move(m__io->read_f8le()));
    }
    m_m_range = std::unique_ptr<bounds_min_max_t>(new bounds_min_max_t(m__io, this, m__root));
    m_m_values = std::unique_ptr<std::vector<double>>(new std::vector<double>());
    const int l_m_values = number_of_points();
    for (int i = 0; i < l_m_values; i++) {
        m_m_values->push_back(std::move(m__io->read_f8le()));
    }
}

shapefile_main_t::poly_line_z_t::~poly_line_z_t() {
    _clean_up();
}

void shapefile_main_t::poly_line_z_t::_clean_up() {
}

shapefile_main_t::polygon_z_t::polygon_z_t(kaitai::kstream* p__io, shapefile_main_t::record_contents_t* p__parent, shapefile_main_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    m_bounding_box = nullptr;
    m_parts = nullptr;
    m_points = nullptr;
    m_z_range = nullptr;
    m_z_values = nullptr;
    m_m_range = nullptr;
    m_m_values = nullptr;
    _read();
}

void shapefile_main_t::polygon_z_t::_read() {
    m_bounding_box = std::unique_ptr<bounding_box_x_y_t>(new bounding_box_x_y_t(m__io, this, m__root));
    m_number_of_parts = m__io->read_s4le();
    m_number_of_points = m__io->read_s4le();
    m_parts = std::unique_ptr<std::vector<int32_t>>(new std::vector<int32_t>());
    const int l_parts = number_of_parts();
    for (int i = 0; i < l_parts; i++) {
        m_parts->push_back(std::move(m__io->read_s4le()));
    }
    m_points = std::unique_ptr<std::vector<std::unique_ptr<point_t>>>(new std::vector<std::unique_ptr<point_t>>());
    const int l_points = number_of_points();
    for (int i = 0; i < l_points; i++) {
        m_points->push_back(std::move(std::unique_ptr<point_t>(new point_t(m__io, this, m__root))));
    }
    m_z_range = std::unique_ptr<bounds_min_max_t>(new bounds_min_max_t(m__io, this, m__root));
    m_z_values = std::unique_ptr<std::vector<double>>(new std::vector<double>());
    const int l_z_values = number_of_points();
    for (int i = 0; i < l_z_values; i++) {
        m_z_values->push_back(std::move(m__io->read_f8le()));
    }
    m_m_range = std::unique_ptr<bounds_min_max_t>(new bounds_min_max_t(m__io, this, m__root));
    m_m_values = std::unique_ptr<std::vector<double>>(new std::vector<double>());
    const int l_m_values = number_of_points();
    for (int i = 0; i < l_m_values; i++) {
        m_m_values->push_back(std::move(m__io->read_f8le()));
    }
}

shapefile_main_t::polygon_z_t::~polygon_z_t() {
    _clean_up();
}

void shapefile_main_t::polygon_z_t::_clean_up() {
}

shapefile_main_t::bounding_box_x_y_t::bounding_box_x_y_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, shapefile_main_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    m_x = nullptr;
    m_y = nullptr;
    _read();
}

void shapefile_main_t::bounding_box_x_y_t::_read() {
    m_x = std::unique_ptr<bounds_min_max_t>(new bounds_min_max_t(m__io, this, m__root));
    m_y = std::unique_ptr<bounds_min_max_t>(new bounds_min_max_t(m__io, this, m__root));
}

shapefile_main_t::bounding_box_x_y_t::~bounding_box_x_y_t() {
    _clean_up();
}

void shapefile_main_t::bounding_box_x_y_t::_clean_up() {
}

shapefile_main_t::point_m_t::point_m_t(kaitai::kstream* p__io, shapefile_main_t::record_contents_t* p__parent, shapefile_main_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    _read();
}

void shapefile_main_t::point_m_t::_read() {
    m_x = m__io->read_f8le();
    m_y = m__io->read_f8le();
    m_m = m__io->read_f8le();
}

shapefile_main_t::point_m_t::~point_m_t() {
    _clean_up();
}

void shapefile_main_t::point_m_t::_clean_up() {
}

shapefile_main_t::polygon_m_t::polygon_m_t(kaitai::kstream* p__io, shapefile_main_t::record_contents_t* p__parent, shapefile_main_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    m_bounding_box = nullptr;
    m_parts = nullptr;
    m_points = nullptr;
    m_m_range = nullptr;
    m_m_values = nullptr;
    _read();
}

void shapefile_main_t::polygon_m_t::_read() {
    m_bounding_box = std::unique_ptr<bounding_box_x_y_t>(new bounding_box_x_y_t(m__io, this, m__root));
    m_number_of_parts = m__io->read_s4le();
    m_number_of_points = m__io->read_s4le();
    m_parts = std::unique_ptr<std::vector<int32_t>>(new std::vector<int32_t>());
    const int l_parts = number_of_parts();
    for (int i = 0; i < l_parts; i++) {
        m_parts->push_back(std::move(m__io->read_s4le()));
    }
    m_points = std::unique_ptr<std::vector<std::unique_ptr<point_t>>>(new std::vector<std::unique_ptr<point_t>>());
    const int l_points = number_of_points();
    for (int i = 0; i < l_points; i++) {
        m_points->push_back(std::move(std::unique_ptr<point_t>(new point_t(m__io, this, m__root))));
    }
    m_m_range = std::unique_ptr<bounds_min_max_t>(new bounds_min_max_t(m__io, this, m__root));
    m_m_values = std::unique_ptr<std::vector<double>>(new std::vector<double>());
    const int l_m_values = number_of_points();
    for (int i = 0; i < l_m_values; i++) {
        m_m_values->push_back(std::move(m__io->read_f8le()));
    }
}

shapefile_main_t::polygon_m_t::~polygon_m_t() {
    _clean_up();
}

void shapefile_main_t::polygon_m_t::_clean_up() {
}

shapefile_main_t::record_header_t::record_header_t(kaitai::kstream* p__io, shapefile_main_t::record_t* p__parent, shapefile_main_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    _read();
}

void shapefile_main_t::record_header_t::_read() {
    m_record_number = m__io->read_s4be();
    m_content_length = m__io->read_s4be();
}

shapefile_main_t::record_header_t::~record_header_t() {
    _clean_up();
}

void shapefile_main_t::record_header_t::_clean_up() {
}

shapefile_main_t::multi_point_t::multi_point_t(kaitai::kstream* p__io, shapefile_main_t::record_contents_t* p__parent, shapefile_main_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    m_bounding_box = nullptr;
    m_points = nullptr;
    _read();
}

void shapefile_main_t::multi_point_t::_read() {
    m_bounding_box = std::unique_ptr<bounding_box_x_y_t>(new bounding_box_x_y_t(m__io, this, m__root));
    m_number_of_points = m__io->read_s4le();
    m_points = std::unique_ptr<std::vector<std::unique_ptr<point_t>>>(new std::vector<std::unique_ptr<point_t>>());
    const int l_points = number_of_points();
    for (int i = 0; i < l_points; i++) {
        m_points->push_back(std::move(std::unique_ptr<point_t>(new point_t(m__io, this, m__root))));
    }
}

shapefile_main_t::multi_point_t::~multi_point_t() {
    _clean_up();
}

void shapefile_main_t::multi_point_t::_clean_up() {
}

shapefile_main_t::file_header_t::file_header_t(kaitai::kstream* p__io, shapefile_main_t* p__parent, shapefile_main_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    m_bounding_box = nullptr;
    _read();
}

void shapefile_main_t::file_header_t::_read() {
    m_file_code = m__io->read_bytes(4);
    if (!(file_code() == std::string("\x00\x00\x27\x0A", 4))) {
        throw kaitai::validation_not_equal_error<std::string>(std::string("\x00\x00\x27\x0A", 4), file_code(), _io(), std::string("/types/file_header/seq/0"));
    }
    m_unused_field_1 = m__io->read_bytes(4);
    if (!(unused_field_1() == std::string("\x00\x00\x00\x00", 4))) {
        throw kaitai::validation_not_equal_error<std::string>(std::string("\x00\x00\x00\x00", 4), unused_field_1(), _io(), std::string("/types/file_header/seq/1"));
    }
    m_unused_field_2 = m__io->read_bytes(4);
    if (!(unused_field_2() == std::string("\x00\x00\x00\x00", 4))) {
        throw kaitai::validation_not_equal_error<std::string>(std::string("\x00\x00\x00\x00", 4), unused_field_2(), _io(), std::string("/types/file_header/seq/2"));
    }
    m_unused_field_3 = m__io->read_bytes(4);
    if (!(unused_field_3() == std::string("\x00\x00\x00\x00", 4))) {
        throw kaitai::validation_not_equal_error<std::string>(std::string("\x00\x00\x00\x00", 4), unused_field_3(), _io(), std::string("/types/file_header/seq/3"));
    }
    m_unused_field_4 = m__io->read_bytes(4);
    if (!(unused_field_4() == std::string("\x00\x00\x00\x00", 4))) {
        throw kaitai::validation_not_equal_error<std::string>(std::string("\x00\x00\x00\x00", 4), unused_field_4(), _io(), std::string("/types/file_header/seq/4"));
    }
    m_unused_field_5 = m__io->read_bytes(4);
    if (!(unused_field_5() == std::string("\x00\x00\x00\x00", 4))) {
        throw kaitai::validation_not_equal_error<std::string>(std::string("\x00\x00\x00\x00", 4), unused_field_5(), _io(), std::string("/types/file_header/seq/5"));
    }
    m_file_length = m__io->read_s4be();
    m_version = m__io->read_bytes(4);
    if (!(version() == std::string("\xE8\x03\x00\x00", 4))) {
        throw kaitai::validation_not_equal_error<std::string>(std::string("\xE8\x03\x00\x00", 4), version(), _io(), std::string("/types/file_header/seq/7"));
    }
    m_shape_type = static_cast<shapefile_main_t::shape_type_t>(m__io->read_s4le());
    m_bounding_box = std::unique_ptr<bounding_box_x_y_z_m_t>(new bounding_box_x_y_z_m_t(m__io, this, m__root));
}

shapefile_main_t::file_header_t::~file_header_t() {
    _clean_up();
}

void shapefile_main_t::file_header_t::_clean_up() {
}

shapefile_main_t::point_z_t::point_z_t(kaitai::kstream* p__io, shapefile_main_t::record_contents_t* p__parent, shapefile_main_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    _read();
}

void shapefile_main_t::point_z_t::_read() {
    m_x = m__io->read_f8le();
    m_y = m__io->read_f8le();
    m_z = m__io->read_f8le();
    m_m = m__io->read_f8le();
}

shapefile_main_t::point_z_t::~point_z_t() {
    _clean_up();
}

void shapefile_main_t::point_z_t::_clean_up() {
}

shapefile_main_t::record_t::record_t(kaitai::kstream* p__io, shapefile_main_t* p__parent, shapefile_main_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    m_header = nullptr;
    m_contents = nullptr;
    _read();
}

void shapefile_main_t::record_t::_read() {
    m_header = std::unique_ptr<record_header_t>(new record_header_t(m__io, this, m__root));
    m_contents = std::unique_ptr<record_contents_t>(new record_contents_t(m__io, this, m__root));
}

shapefile_main_t::record_t::~record_t() {
    _clean_up();
}

void shapefile_main_t::record_t::_clean_up() {
}

shapefile_main_t::record_contents_t::record_contents_t(kaitai::kstream* p__io, shapefile_main_t::record_t* p__parent, shapefile_main_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    _read();
}

void shapefile_main_t::record_contents_t::_read() {
    m_shape_type = static_cast<shapefile_main_t::shape_type_t>(m__io->read_s4le());
    n_shape_parameters = true;
    if (shape_type() != shapefile_main_t::SHAPE_TYPE_NULL_SHAPE) {
        n_shape_parameters = false;
        n_shape_parameters = true;
        switch (shape_type()) {
        case shapefile_main_t::SHAPE_TYPE_POLY_LINE_Z: {
            n_shape_parameters = false;
            m_shape_parameters = std::unique_ptr<poly_line_z_t>(new poly_line_z_t(m__io, this, m__root));
            break;
        }
        case shapefile_main_t::SHAPE_TYPE_MULTI_PATCH: {
            n_shape_parameters = false;
            m_shape_parameters = std::unique_ptr<multi_patch_t>(new multi_patch_t(m__io, this, m__root));
            break;
        }
        case shapefile_main_t::SHAPE_TYPE_POLY_LINE_M: {
            n_shape_parameters = false;
            m_shape_parameters = std::unique_ptr<poly_line_m_t>(new poly_line_m_t(m__io, this, m__root));
            break;
        }
        case shapefile_main_t::SHAPE_TYPE_POLYGON: {
            n_shape_parameters = false;
            m_shape_parameters = std::unique_ptr<polygon_t>(new polygon_t(m__io, this, m__root));
            break;
        }
        case shapefile_main_t::SHAPE_TYPE_POLYGON_Z: {
            n_shape_parameters = false;
            m_shape_parameters = std::unique_ptr<polygon_z_t>(new polygon_z_t(m__io, this, m__root));
            break;
        }
        case shapefile_main_t::SHAPE_TYPE_POINT_Z: {
            n_shape_parameters = false;
            m_shape_parameters = std::unique_ptr<point_z_t>(new point_z_t(m__io, this, m__root));
            break;
        }
        case shapefile_main_t::SHAPE_TYPE_POLY_LINE: {
            n_shape_parameters = false;
            m_shape_parameters = std::unique_ptr<poly_line_t>(new poly_line_t(m__io, this, m__root));
            break;
        }
        case shapefile_main_t::SHAPE_TYPE_POINT_M: {
            n_shape_parameters = false;
            m_shape_parameters = std::unique_ptr<point_m_t>(new point_m_t(m__io, this, m__root));
            break;
        }
        case shapefile_main_t::SHAPE_TYPE_POLYGON_M: {
            n_shape_parameters = false;
            m_shape_parameters = std::unique_ptr<polygon_m_t>(new polygon_m_t(m__io, this, m__root));
            break;
        }
        case shapefile_main_t::SHAPE_TYPE_MULTI_POINT: {
            n_shape_parameters = false;
            m_shape_parameters = std::unique_ptr<multi_point_t>(new multi_point_t(m__io, this, m__root));
            break;
        }
        case shapefile_main_t::SHAPE_TYPE_POINT: {
            n_shape_parameters = false;
            m_shape_parameters = std::unique_ptr<point_t>(new point_t(m__io, this, m__root));
            break;
        }
        case shapefile_main_t::SHAPE_TYPE_MULTI_POINT_M: {
            n_shape_parameters = false;
            m_shape_parameters = std::unique_ptr<multi_point_m_t>(new multi_point_m_t(m__io, this, m__root));
            break;
        }
        case shapefile_main_t::SHAPE_TYPE_MULTI_POINT_Z: {
            n_shape_parameters = false;
            m_shape_parameters = std::unique_ptr<multi_point_z_t>(new multi_point_z_t(m__io, this, m__root));
            break;
        }
        }
    }
}

shapefile_main_t::record_contents_t::~record_contents_t() {
    _clean_up();
}

void shapefile_main_t::record_contents_t::_clean_up() {
    if (!n_shape_parameters) {
    }
}

shapefile_main_t::multi_patch_t::multi_patch_t(kaitai::kstream* p__io, shapefile_main_t::record_contents_t* p__parent, shapefile_main_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    m_bounding_box = nullptr;
    m_parts = nullptr;
    m_part_types = nullptr;
    m_points = nullptr;
    m_z_range = nullptr;
    m_z_values = nullptr;
    m_m_range = nullptr;
    m_m_values = nullptr;
    _read();
}

void shapefile_main_t::multi_patch_t::_read() {
    m_bounding_box = std::unique_ptr<bounding_box_x_y_t>(new bounding_box_x_y_t(m__io, this, m__root));
    m_number_of_parts = m__io->read_s4le();
    m_number_of_points = m__io->read_s4le();
    m_parts = std::unique_ptr<std::vector<int32_t>>(new std::vector<int32_t>());
    const int l_parts = number_of_parts();
    for (int i = 0; i < l_parts; i++) {
        m_parts->push_back(std::move(m__io->read_s4le()));
    }
    m_part_types = std::unique_ptr<std::vector<part_type_t>>(new std::vector<part_type_t>());
    const int l_part_types = number_of_parts();
    for (int i = 0; i < l_part_types; i++) {
        m_part_types->push_back(std::move(static_cast<shapefile_main_t::part_type_t>(m__io->read_s4le())));
    }
    m_points = std::unique_ptr<std::vector<std::unique_ptr<point_t>>>(new std::vector<std::unique_ptr<point_t>>());
    const int l_points = number_of_points();
    for (int i = 0; i < l_points; i++) {
        m_points->push_back(std::move(std::unique_ptr<point_t>(new point_t(m__io, this, m__root))));
    }
    m_z_range = std::unique_ptr<bounds_min_max_t>(new bounds_min_max_t(m__io, this, m__root));
    m_z_values = std::unique_ptr<std::vector<double>>(new std::vector<double>());
    const int l_z_values = number_of_points();
    for (int i = 0; i < l_z_values; i++) {
        m_z_values->push_back(std::move(m__io->read_f8le()));
    }
    m_m_range = std::unique_ptr<bounds_min_max_t>(new bounds_min_max_t(m__io, this, m__root));
    m_m_values = std::unique_ptr<std::vector<double>>(new std::vector<double>());
    const int l_m_values = number_of_points();
    for (int i = 0; i < l_m_values; i++) {
        m_m_values->push_back(std::move(m__io->read_f8le()));
    }
}

shapefile_main_t::multi_patch_t::~multi_patch_t() {
    _clean_up();
}

void shapefile_main_t::multi_patch_t::_clean_up() {
}

shapefile_main_t::poly_line_m_t::poly_line_m_t(kaitai::kstream* p__io, shapefile_main_t::record_contents_t* p__parent, shapefile_main_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    m_bounding_box = nullptr;
    m_parts = nullptr;
    m_points = nullptr;
    m_m_range = nullptr;
    m_m_values = nullptr;
    _read();
}

void shapefile_main_t::poly_line_m_t::_read() {
    m_bounding_box = std::unique_ptr<bounding_box_x_y_t>(new bounding_box_x_y_t(m__io, this, m__root));
    m_number_of_parts = m__io->read_s4le();
    m_number_of_points = m__io->read_s4le();
    m_parts = std::unique_ptr<std::vector<int32_t>>(new std::vector<int32_t>());
    const int l_parts = number_of_parts();
    for (int i = 0; i < l_parts; i++) {
        m_parts->push_back(std::move(m__io->read_s4le()));
    }
    m_points = std::unique_ptr<std::vector<std::unique_ptr<point_t>>>(new std::vector<std::unique_ptr<point_t>>());
    const int l_points = number_of_points();
    for (int i = 0; i < l_points; i++) {
        m_points->push_back(std::move(std::unique_ptr<point_t>(new point_t(m__io, this, m__root))));
    }
    m_m_range = std::unique_ptr<bounds_min_max_t>(new bounds_min_max_t(m__io, this, m__root));
    m_m_values = std::unique_ptr<std::vector<double>>(new std::vector<double>());
    const int l_m_values = number_of_points();
    for (int i = 0; i < l_m_values; i++) {
        m_m_values->push_back(std::move(m__io->read_f8le()));
    }
}

shapefile_main_t::poly_line_m_t::~poly_line_m_t() {
    _clean_up();
}

void shapefile_main_t::poly_line_m_t::_clean_up() {
}