美文网首页
Columnwise.h

Columnwise.h

作者: 微雨旧时歌丶 | 来源:发表于2018-03-19 11:09 被阅读0次

    2018.03.19

    //////////////////////////////////////////////////////////////
    // 该头文件提供了将 osm数据 按照分块,列式存储的方式序列化的基本方法//
    //////////////////////////////////////////////////////////////
    
    #include "osmpbfreader.h"  // 解析osmpbf 的头文件
    #include <fstream>
    #include <iostream>
    #include <iomanip>
    #include <zlib.h> // pbf blobs中使用到了zlib压缩
    #include <stdint.h> // 定义了几种扩展的整数类型和宏
    #include <netinet/in.h> // 提供了network-byte-order的转换函数
    #include <cstdlib> // for exit()
    
    #include <cstring>
    #include <vector>
    #include <map>
    #include <algorithm>
    using namespace std;
    typedef uint8_t byte;
    const int max_block_size = 64*1024*1024;
    const int max_numberbuf_size = 1024*1024; // 数值型缓冲区的最大空间 100KB
    const int max_stringbuf_size = 32 * 1024 * 1024; //存放字符串的最大空间 32MB
    const int group_size = 10000; // 一组中包含同类的、不大于10000个OSM对象
    // ----------------------------------------------------------------
    // module number_buf
    // 这个模块提供将 整型数 以 varint编码方式 写进缓冲区的函数
    // 注意: 这些写入操作并不会使缓冲区当前的写入位置向后移动,
    //       所以如果需要 追加数据 ,则每次执行本操作后
    //       要手动将 缓冲当前写入位置后移 写入的字节数
    static inline int uint32_buf(byte* p, uint32_t v){
        // 将 无符号32位整数 序列化到 目标p所指的内存地址的起始位置中
        // 参数: - p :缓冲区当前写入位置的指针
        //       - v : 无符号32位整数
        // 返回: 写入的字节数
        byte* p0;
        uint32_t frac;
    
        p0= p;
        frac= v&0x7f;
        if(frac==v) {  // just one byte
            *p++= frac;
            return 1;
        }
        do {
            *p++= frac|0x80;
            v>>= 7;
            frac= v&0x7f;
        } while(frac!=v);
        *p++= frac;
        return p-p0;    
    }
    static inline int sint32_buf(byte* p,int32_t v) {
        // 将 有符号32位整数 序列化到 目标p所指的内存地址的起始位置中
        byte* p0;
        uint32_t u;
        uint32_t frac;
    
        p0= p;
        if(v<0) {
            u= -v;
            u= (u<<1)-1;
        }
        else
            u= v<<1;
        frac= u&0x7f;
        if(frac==u) {
            *p++= frac;
            return 1;
        }
        do {
            *p++= frac|0x80;
            u>>= 7;
            frac= u&0x7f;
        } while(frac!=u);
        *p++= frac;
        return p-p0;
    }   
    static inline int sint64_buf(byte* p, int64_t v) {
        // 将 有符号64位整数 序列化到 目标p所指的内存地址的起始位置中
        byte* p0;
        uint64_t u;
        uint32_t frac;
    
        p0= p;
        if(v<0) {
            u= -v;
            u= (u<<1)-1;
        }
        else
            u= v<<1;
        frac= u&0x7f;
        if(frac==u) {
            *p++= frac;
            return 1;
        }
        do {
            *p++= frac|0x80;
            u>>= 7;
            frac= u&0x7f;
        } while(frac!=u);
        *p++= frac;
        return p-p0;
    }
    
    // module number_buf
    // ----------------------------------------------------------------
    
    
    class OSMBuffer{
    private:
        std::ofstream file;
        // 主缓冲区
        byte* Block_Buf = NULL;
        byte* block_bufp = NULL;
        // 为所有OSM属性 定义缓冲区,及操作函数
        byte* Id_Buf = NULL; // id
        byte* id_bufp = NULL; // ID缓冲区的写入指针当前的位置
        // ------------ lon/lat -----------------------
        byte* Lon_Buf = NULL; // longitude
        byte* lon_bufp = NULL; // 写入指针当前位置
        byte* Lat_Buf = NULL; // latitude
        byte* lat_bufp = NULL; // 写入指针当前位置
        // ----------- tags: key/val(字符串型) ------------------
        byte* KeyVal_Buf = NULL; // key/val共用一块缓冲区
        byte* keyval_bufp = NULL; 
        // 字符串型数据都要配有 索引缓冲区
        byte* KeyValId_Buf = NULL; // key/val的索引缓冲区
        byte* keyvalid_bufp = NULL;
        // ------------ info --------------------------
        byte* Version_Buf = NULL; // version
        byte* version_bufp = NULL;
        byte* Time_Buf = NULL; // timestamp
        byte* time_bufp = NULL; 
        byte* Cset_Buf = NULL; //changeset
        byte* cset_bufp = NULL;
        byte* Uid_Buf = NULL; //user_id
        byte* uid_bufp = NULL;
        byte* Uname_Buf = NULL; // user_name
        byte* uname_bufp = NULL;
        // ------------ 参考成员的ID,way和relation可共用 --------
        byte* RefId_Buf = NULL;
        byte* refid_bufp = NULL;
        // ------------ Relation的参考成员中还包括 member_type 和 role -----
        byte* Type_Buf = NULL; // member_type (0-node,1-way,2-relation)
        byte* type_bufp = NULL;
        byte* Role_Buf = NULL; // member_role (string)
        byte* role_bufp = NULL; 
    
    protected:
        // 字符串表操作的基础
        // 用STL的map来完成字符串的查找和插入,key和val一同(交替)处理
        map<string,uint32_t> string_index; 
        map<string,uint32_t>::iterator it_map; // 迭代器
        uint32_t index = 0; // 字符串索引计数器
        // delta 编码的基础
        int64_t temp_id;
        uint32_t temp_lat,temp_lon;
        int64_t temp_cset;
        int64_t temp_time;
        int64_t temp_ref[3];  // for node, way, relation
        // 对象数量计数器
        int count = 0; // count< group_size
        int osm_type = -1; // 当前处理的OSM类型标记,0-node,1-way,2-relation
    public:
        OSMBuffer(){};
    
        void osm_reset_vars(){
            // 重置所有的delta编码计数器,应该在写完一个文件块之后调用
            temp_id = 0;
            temp_lon = temp_lat = 0;
            temp_cset = 0;
            temp_time = 0;
            temp_ref[0] = temp_ref[1] = temp_ref[2]=0;
            count = 0;
            index = 0;
    
            string_index.clear(); // 
        }
        void osm_reset(){ // 缓冲区指针头重置
            block_bufp = Block_Buf; // 主缓冲区
    
            id_bufp = Id_Buf; // id
    
            lon_bufp = Lon_Buf; // lon
            lat_bufp = Lat_Buf; // lat
    
            keyval_bufp = KeyVal_Buf; // key/val
            keyvalid_bufp = KeyValId_Buf; // key/val的索引指针的重置
    //      valid_bufp = ValId_Buf;
    
            version_bufp = Version_Buf; // version
            time_bufp = Time_Buf; // timestamp
            cset_bufp = Cset_Buf; //changset
            uid_bufp = Uid_Buf; // user_id
            uname_bufp = Uname_Buf; // user_name
            refid_bufp = RefId_Buf; // refID
            type_bufp = Type_Buf; // member_type
            role_bufp = Role_Buf; // member_role
        }
        void osm_end() {
            // 清理模块内的缓冲区
            // 将在程序结尾调用;
            delete [] Block_Buf;
    
            delete [] Id_Buf; // id
            delete [] Lon_Buf; // lon
    
            delete [] Lat_Buf; // lat
            delete [] KeyVal_Buf; // key/val
            delete [] KeyValId_Buf;
    //      delete [] ValId_Buf;
    
            delete [] Version_Buf; // version
            delete [] Time_Buf; // timestamp
            delete [] Cset_Buf; //changset
            delete [] Uid_Buf; // user_id
            delete [] Uname_Buf; // user_name
            delete [] RefId_Buf; // refID
            delete [] Type_Buf; // member_type
            delete [] Role_Buf; // member_role
    
            file.close();
        }  // end
    
        int osm_ini(const std::string filename){
            // 初始化类,须在调用其他函数之前调用它
            // 返回值: 0-正常  !0 - 出错
            file.open(filename); // 打开输出文件
            if(!file.is_open()){
                std::cerr<<"Can't open "<<filename<<" file for output\n";
                exit(EXIT_FAILURE);
            }   
    
            Block_Buf = new byte[max_block_size];
            // --------------数值型 9个 --------------------
            Id_Buf = new byte[max_numberbuf_size];
            Lon_Buf = new byte[max_numberbuf_size];
            Lat_Buf = new byte[max_numberbuf_size];
            
            Version_Buf = new byte[max_numberbuf_size];
            Time_Buf = new byte[max_numberbuf_size];
            Cset_Buf = new byte[max_numberbuf_size];
            Uid_Buf = new byte[max_numberbuf_size];
            RefId_Buf = new byte[max_numberbuf_size];
            Type_Buf = new byte[max_numberbuf_size];
    
            KeyValId_Buf = new byte[max_numberbuf_size]; // 索引
    //      ValId_Buf = new byte[max_numberbuf_size];
            // -------------字符串型 4个 --------------------
            KeyVal_Buf = new byte[max_stringbuf_size];
    
            Uname_Buf = new byte[max_stringbuf_size];
            Role_Buf = new byte[max_stringbuf_size];
            osm_reset();
            return 0;
        }  
        // 返回各缓冲区的内存占用情况
        int Block_Buf_Size(){ return block_bufp - Block_Buf;}
    
        int Id_Buf_Size(){ return id_bufp - Id_Buf; }
        int Lon_Buf_Size(){ return lon_bufp - Lon_Buf; }
        int Lat_Buf_Size(){ return lat_bufp - Lat_Buf; }
    
        int Version_Buf_Size(){ return version_bufp - Version_Buf; }
        int Time_Buf_Size(){ return time_bufp - Time_Buf;}
        int Cset_Buf_Size(){ return cset_bufp - Cset_Buf;}
        int Uid_Buf_Size(){ return uid_bufp - Uid_Buf;}
        int RefId_Buf_Size(){ return refid_bufp - RefId_Buf;}
        int Type_Buf_Size(){ return type_bufp - Type_Buf;}
    
        int KeyVal_Buf_Size(){ return keyval_bufp - KeyVal_Buf; }
        int KeyValId_Buf_Size(){return keyvalid_bufp - KeyValId_Buf;}
    //  int ValId_Buf_Size(){return valid_bufp - ValId_Buf;}
    
        int Uname_Buf_Size(){ return uname_bufp - Uname_Buf;}
        int Role_Buf_Size(){ return role_bufp - Role_Buf; }
        // 判断各缓冲区是否接近满
        bool Block_Buf_Full(int total_len){
            // 判断主缓冲区是否有足够的剩余空间存储 total_len 长度的数据
            return Block_Buf_Size() + total_len >0.9*max_block_size?true:false;
        }
        // 数值型
        bool Id_Buf_Full(){ 
            return Id_Buf_Size()> 0.9*max_numberbuf_size?true:false;
        }
        bool Lon_Buf_Full(){
            return Lon_Buf_Size()>0.9*max_numberbuf_size?true:false;
        }
        bool Lat_Buf_Full(){
            return Lat_Buf_Size()>0.9*max_numberbuf_size?true:false;
        }   
        bool Version_Buf_Full(){
            return Version_Buf_Size()>0.9*max_numberbuf_size?true:false;
        }
        bool Time_Buf_Full(){
            return Time_Buf_Size()>0.9*max_numberbuf_size?true:false;
        }
        bool Cset_Buf_Full(){
            return Cset_Buf_Size()>0.9*max_numberbuf_size?true:false;
        }
        bool Uid_Buf_Full(){
            return Uid_Buf_Size()>0.9*max_numberbuf_size?true:false;
        }
        bool RefId_Buf_Full(){
            return RefId_Buf_Size()>0.9*max_numberbuf_size?true:false;
        }
        bool Type_Buf_Full(){
            return Type_Buf_Size()>0.9*max_numberbuf_size?true:false;
        }
    
        bool KeyValId_Buf_Full(){
            return KeyValId_Buf_Size()>0.9*max_numberbuf_size?true:false;
        }
    //  bool ValId_Buf_Full(){
    //      return ValId_Buf_Size()>0.9*max_numberbuf_size?true:false;
    //  }
        // 字符串型
        bool KeyVal_Buf_Full(){
            return KeyVal_Buf_Size()>0.9*max_stringbuf_size?true:false;
        }
    
        bool Uname_Buf_Full(){
            return Uname_Buf_Size()>0.9*max_stringbuf_size?true:false;
        }
        bool Role_Buf_Full(){
            return Role_Buf_Size()>0.9*max_stringbuf_size?true:false;
        }       
    
        // ---- 1. 对数值型缓冲区的 写入操作 ----------------------------
        // 功能说明: 提供将 不同类型的数据 以varint 方式写入对应缓冲区的功能
        // 注意: *************暂时没有加入缓冲区满空状态检查*************
        // ------ 1.1 无重复的数值型数据的写入处理 ----------------------
        // 写id
        void write_id(int64_t id){
            // 向 ID 缓冲区中以varint方式写入id
            // 从缓冲区数据当前位置 id_bufp 开始写入 
            int len = sint64_buf(id_bufp, id); // 缓冲区当前位置指针后移
            id_bufp +=len;
        }
        // 写经纬度坐标 (输入为 int32_t 整数)
        void write_lon(int32_t lon){
            lon_bufp += sint32_buf(lon_bufp,lon);
        }
        void write_lat(int32_t lat){
            lat_bufp += sint32_buf(lat_bufp,lat);
        }
        // 写 用户信息 (数值部分)
        void write_version(uint32_t version){
            version_bufp +=uint32_buf(version_bufp,version);
        }
        void write_time(int64_t timestamp){
            time_bufp +=sint64_buf(time_bufp,timestamp);
        }
        void write_cset(int64_t changset){
            cset_bufp +=sint64_buf(cset_bufp,changset);
        }
        void write_uid(uint32_t uid){ // 是不是应该把 uid和uname放一起组成字符串
            uid_bufp +=uint32_buf(uid_bufp,uid);
        }
        // ------ 1.2 重复的数值型数据字段 --------------------------------
        //////////////////////////////////////////////////////////////////
        // ------ 2. key/val 写入 key_val 缓冲区的操作 -------------------
        void write_keyvalid(uint32_t stringid){
            // 向 keyvalid 缓冲区中写入一个 无符号32位整数 
            keyvalid_bufp += uint32_buf(keyvalid_bufp,stringid);
        }
        int write_keyval(const char* s){
            // 写一个“以零为终止符”的字符串; 、、、考虑改输入类型为string
            // 在 keyval_bufp 位置开始写,写入完成 keyval_bufp指针将后移
            // 返回:增加的字节数
            byte* p0;
            byte c;
            p0 = keyval_bufp;
            // ---- 检查满空状态 -------
            do *keyval_bufp++= c=*s++;
                while(c!=0);
            return keyval_bufp - p0; // 返回是写入的字节数
        }
        void write_tags(const Tags &tags){
            // 向 key/val缓冲区中写入字符串
            // 通过map的查找功能滤掉重复的字符串
            // keyid/valid 也存入同一缓冲区,交替存储
            // keyval_id 缓冲区的存储模式为:** size + (重复的)key_id + val_id **
            // /////并向 keyvalid 缓冲区中写入对应的索引值
            
            // 先向 keyvalid缓冲区中写入 key/val的数量
            write_keyvalid(tags.size());
            // 处理key/val
            for (auto it = tags.begin();it!=tags.end();++it){ // 对tags中的每对 key/val进行遍历
                // 得到 key/val
                std::string key = it->first;
                std::string val = it->second;
                // key 的处理
                it_map = string_index.find(key); // 在map中寻找key
                if(it_map != string_index.end()){
                    // map中已经存在相同的字符串 
                    // 直接把该字符串的索引存入 keyvalid 缓冲区即可,索引在second中
                    write_keyvalid(it_map->second);
                }
                else {
                    // map中尚不存在该字符串,则 将该字符串存进map, string - index
                    string_index[key] = index;
                    // 将该字符串存进 key/val缓冲区
                    write_keyval(key.c_str()); // 字符串以零做分隔符
                    // 把这个key的索引值存入 keyvalid缓冲区
                    write_keyvalid(index++);
                }
                // val 的处理
                it_map = string_index.find(val); // 在map中寻找val
                if (it_map != string_index.end()){
                    write_keyvalid(it_map->second);
                }
                else {
                    string_index[val] = index;
                    write_keyval(val.c_str());
                    write_keyvalid(index++);                
                }
            }
        }
    
        // ------- 写入对象的操作 ----------------------------------------
    
        void write_byte_toblockbuf(byte b) {
            // 向 主缓冲区 中写入一个字节(字符);
            *block_bufp++ = b;
        }  // end
        void write_len_toblockbuf(uint32_t len){
            block_bufp +=uint32_buf(block_bufp,len);
        }   
        int write_Node(int64_t id,double lon,double lat,Info info,Tags tags){
            // 将一组(≤10000)个节点写入文件块
            // 接口: 经纬度坐标为double型,需乘以放大倍数1e7并转换类型为int32_t
            // 返回: 0 成功; !=0 失败 
            // 将id写入id缓冲区(delta-coding)
            if (osm_type == -1){
                // 第一次运行
                osm_reset_vars(); // delta计数器重置
                osm_reset(); // 缓冲区指针重置         
            }
            else if (osm_type !=0){
                write_block();
                SerializeToFile();
                // 1)当前处理的对象类型与之前发生了改变,
                // 2)或者写入一组对象数量已满时,
                // 需要先将之前的各缓冲区序列化进文件
                /*
                if (osm_type =1){
                    // way
                    //------ 调用序列化way缓冲区的写入文件操作 ---------
                }
                else if (osm_type =2){
                    // relation
                    //------ 调用序列化relation缓冲区的写入文件操作-----
                }
                osm_reset_vars(); // delta计数器重置
                osm_reset(); // 缓冲区指针重置
                */
            }
            else if (osm_type==0 && count>=group_size){
                // 对象数量已满
                // --------- 调用序列化node缓冲区的写入文件操作 --------
                write_block();
            //  SerializeToFile(osm_type,&file);
                SerializeToFile();
            //  cout << osm_type;
            //  osm_reset_vars(); // delta计数器重置
            //  osm_reset(); // 缓冲区指针重置
            }
            osm_type = 0; // 设置类型标识为node
            count++; // 对象计数器加1
            write_id(id-temp_id); temp_id = id; 
            // 将lon写入lon缓冲区 delta-coding
            write_lon(int32_t(lon*1e7)-temp_lon); temp_lon = int32_t(lon*1e7);
            // 将lat写入lat缓冲区 delta-coding
            write_lat(int32_t(lat*1e7)-temp_lat); temp_lat = int32_t(lat*1e7); 
            write_version(info.version);
            write_time(info.timestamp-temp_time); temp_time = info.timestamp;
            write_cset(info.changeset-temp_cset); temp_cset = info.changeset;
            write_tags(tags); // 写key/val
        }
        ///////////////////////////////////////////////////////////////////////////////
        // ------------------- 将各字段array写入主缓冲区的操作 -------------------
        void write_id_array(){
            // 将 ID array写入 blockbuf     id标识符+长度+id数据
            int len = Id_Buf_Size(); // 获取id列的长度
            write_byte_toblockbuf(0x11); //写id的标识符 0x11
            write_len_toblockbuf(len); // 写入id列的长度信息
            memcpy(block_bufp,Id_Buf,len); // 写入id列的数据内容
            block_bufp += len; // 主缓冲区指针后移      
        }
        void write_lon_array(){
            // 将 节点坐标 的lon array写入 blockbuf    lon标识符+长度+数据
            int len = Lon_Buf_Size();
            write_byte_toblockbuf(0x12); //写lon的标识符 0x12
            write_len_toblockbuf(len);
            memcpy(block_bufp,Lon_Buf,len); // 写入id列的数据内容
            block_bufp +=len;       
        }
        void write_lat_array(){
            // 将 节点坐标 的lat array写入 blockbuf    lat标识符+长度+数据
            int len = Lat_Buf_Size();
            write_byte_toblockbuf(0x13); //写lat的标识符 0x13
            write_len_toblockbuf(len);
            memcpy(block_bufp,Lat_Buf,len);
            block_bufp +=len;       
        }
        void write_version_array(){
            // 写用户信息 版本号
            int len = Version_Buf_Size(); 
            write_byte_toblockbuf(0x21); // version 的标识符 0x21
            write_len_toblockbuf(len); 
            memcpy(block_bufp,Version_Buf,len); 
            block_bufp += len;              
        }
        void write_time_array(){
            // 写用户信息 时间戳
            int len = Time_Buf_Size(); 
            write_byte_toblockbuf(0x22); // timestamp 的标识符 0x22
            write_len_toblockbuf(len); 
            memcpy(block_bufp,Time_Buf,len); 
            block_bufp += len;          
        }
        void write_cset_array(){
            // 写用户信息 变更集
            int len = Cset_Buf_Size(); 
            write_byte_toblockbuf(0x23); // changeset 的标识符 0x23
            write_len_toblockbuf(len); 
            memcpy(block_bufp,Cset_Buf,len); 
            block_bufp += len;          
        }
        void write_uid_array(){ // 是不是应该把 uid和uname放一起组成字符串
            // 写用户信息 用户id
            int len = Uid_Buf_Size(); 
            write_byte_toblockbuf(0x24); // user_id 的标识符 0x24
            write_len_toblockbuf(len); 
            memcpy(block_bufp,Uid_Buf,len); 
            block_bufp += len;  
        }   
        void write_keyvalid_array(){
            // 1) 先把keyval的索引写入 block (即 将keyvalid_buf 拷贝进 block_buf)
            int len = KeyValId_Buf_Size();
            write_byte_toblockbuf(0x31); // keyvalid 的标识符
            write_len_toblockbuf(len);
            memcpy(block_bufp,KeyValId_Buf,len);
            block_bufp +=len;
        }
        void write_keyval_array(){
            // 写 key/val 字符串对array 到主缓冲区
            int len = KeyVal_Buf_Size(); // 获取key/val 缓冲区的大小
            write_byte_toblockbuf(0x41); // key/val 字符串表的标识符
            write_len_toblockbuf(len);
            memcpy(block_bufp,KeyVal_Buf,len);
            block_bufp += len;
        }
        // ------------------- 将各字段array写入主缓冲区的操作 结束 ---------------
        ////////////////////////////////////////////////////////////////////////////////
        int write_block(){
            // 将列式存储的一组OSM对象的缓冲区写入主缓冲区
            // osm_type: 0-node,1-way,2-relation
            int total_len = 0; // 记录块中数据总长度
            int len = 0; // 记录各缓冲区长度
            if (osm_type == 0){
                // node
                total_len = Id_Buf_Size() + Lon_Buf_Size() + Lat_Buf_Size()+
                        KeyVal_Buf_Size() + KeyValId_Buf_Size() + Version_Buf_Size()
                        + Time_Buf_Size() + Cset_Buf_Size();
                if (Block_Buf_Full(total_len)){ // 主缓冲区剩余空间不足
                    std::cerr<<"Error: block-buffer overflow!\n";
                    exit(EXIT_FAILURE); 
                }
                write_keyval_array(); // 在 block 头首先写入 keyval 字符串array缓冲区
    
                write_id_array(); 
    
                write_lon_array();
                write_lat_array();
    
                write_keyvalid_array(); //写入 字符串索引缓冲区 到block
    
                write_version_array();
                write_time_array();
                write_cset_array();
            }
            else if (osm_type = 1){
                // way
            }
            else if (osm_type = 2){
                // relation
            }
        }
        //////////////  测试用 ////////////////////////////////////
        int memcpy_ID_toblock(){
            int len = Id_Buf_Size(); // 获取id列的长度
            write_byte_toblockbuf(0x11); //写id的标识符 0x11
            write_len_toblockbuf(len); // 写入id列的长度信息
            memcpy(block_bufp,Id_Buf,len); // 写入id列的数据内容
            block_bufp += len; // 主缓冲区指针后移      
        }
        void show_id_buffer(){
            int i;
            for (i=0;i<Id_Buf_Size();++i)
                cout<<"0x"<<std::hex<<int(Id_Buf[i])<<" ";
            cout<<endl;
        }
        void show_block_buffer(){
            int i;
            for (i=0;i<Block_Buf_Size();++i)
                cout<<"0x"<<std::hex<<int(Block_Buf[i])<<" ";
            cout<<endl;
        }
    //  int SerializeToFile(){
    
    //  }
        /////////////  测试用 ////////////////////////////////////
    
    
    //  int SerializeToFile(int type,std::ofstream &file){
        int SerializeToFile(){
            // 将block内容写入文件
            // 对象类型 - 长度 - 数据
            byte lenbuf[30];
            int block_len = Block_Buf_Size();
            // 写入block对象类型
            file.put(osm_type+0x01); // 0x01 - node, 0x02 - way, 0x03-relation
            // 写入block长度
            file.write((char*)&lenbuf,uint32_buf(lenbuf,block_len));
            // 写入block数据
            file.write((char*) Block_Buf,block_len);
            osm_reset(); // 指针重置
            osm_reset_vars(); // delta编码计数器重置
        }
        void write_end_tofile(){
            file.put(0xfe);
        }
    };
    
    

    相关文章

      网友评论

          本文标题:Columnwise.h

          本文链接:https://www.haomeiwen.com/subject/spbuqftx.html