From e124e7544119fc16a82a6c02ef05a524d5b6ae9a Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Tue, 29 Mar 2005 19:18:59 +0000 Subject: [PATCH] portable i/o (almost) --- src/shape/dbffile.cc | 31 +++--- src/shape/dbffile.hh | 20 ++-- src/shape/shape_featureset.cc | 13 +-- src/shape/shape_index_featureset.cc | 52 +++++------ src/shape/shape_io.cc | 109 ++++++++++++++-------- src/shape/shape_io.hh | 8 +- src/shape/shapefile.cc | 5 +- src/shape/shapefile.hh | 140 ++++++++++++++++++---------- src/shape/shp_index.cc | 4 +- 9 files changed, 221 insertions(+), 161 deletions(-) diff --git a/src/shape/dbffile.cc b/src/shape/dbffile.cc index c9b382c87..b220bfcfb 100644 --- a/src/shape/dbffile.cc +++ b/src/shape/dbffile.cc @@ -42,7 +42,7 @@ dbf_file::dbf_file(const char* file_name) dbf_file::~dbf_file() { - delete [] record_; + ::operator delete(record_); file_.close(); } @@ -118,7 +118,7 @@ void dbf_file::add_attribute(int col,Feature* f) const switch (fields_[col].type_) { case 'C': - case 'D': //todo handle date? + case 'D'://todo handle date? case 'M': f->add(name,attribute(str)); break; @@ -132,16 +132,15 @@ void dbf_file::add_attribute(int col,Feature* f) const } } - void dbf_file::read_header() { char c=file_.get(); if (c=='\3' || c=='\131') { skip(3); - read_int(num_records_); + num_records_=read_int(); assert(num_records_>0); - read_short(num_fields_); + num_fields_=read_short(); assert(num_fields_>0); num_fields_=(num_fields_-33)/32; skip(22); @@ -163,39 +162,31 @@ void dbf_file::read_header() skip(14); desc.offset_=offset; offset+=desc.length_; - //std::cout <<"name="<0) { - record_=new char[record_length_]; + record_=static_cast(::operator new (sizeof(char)*record_length_)); } } } -void dbf_file::read_short(int& n) +int dbf_file::read_short() { char b[2]; file_.read(b,2); - memcpy(&n,b,2); + return (b[0] & 0xff) | (b[1] & 0xff) << 8; } -void dbf_file::read_int(int& n) -{ +int dbf_file::read_int() +{ char b[4]; file_.read(b,4); - memcpy(&n,b,4); -} - - -void dbf_file::read_double(double& d) -{ - char b[8]; - file_.read(b,8); - memcpy(&d,b,8); + return (b[0] & 0xff) | (b[1] & 0xff) << 8 | + (b[2] & 0xff) << 16 | (b[3] & 0xff) <<24; } diff --git a/src/shape/dbffile.hh b/src/shape/dbffile.hh index 3e9284367..e5234456c 100644 --- a/src/shape/dbffile.hh +++ b/src/shape/dbffile.hh @@ -23,8 +23,6 @@ #include #include #include -//#include - #include "mapnik.hh" @@ -32,13 +30,12 @@ using namespace mapnik; struct field_descriptor { - public: - int index_; - std::string name_; - char type_; - int length_; - int dec_; - int offset_; + int index_; + std::string name_; + char type_; + int length_; + int dec_; + int offset_; }; class dbf_file @@ -76,9 +73,8 @@ class dbf_file dbf_file(const dbf_file&); dbf_file& operator=(const dbf_file&); void read_header(); - void read_short(int& n); - void read_int(int& n); - void read_double(double& d); + int read_short(); + int read_int(); void skip(int bytes); }; #endif //DBFFILE_HH diff --git a/src/shape/shape_featureset.cc b/src/shape/shape_featureset.cc index c9c8b0168..8d21b4fc0 100644 --- a/src/shape/shape_featureset.cc +++ b/src/shape/shape_featureset.cc @@ -47,19 +47,20 @@ Feature* ShapeFeatureset::next() if (type == shape_io::shape_point) { - coord c; - shape_.shp().read_coord(c); + double x=shape_.shp().read_double(); + double y=shape_.shp().read_double(); geometry_ptr point(new point_impl(-1)); - point->move_to(c.x,c.y); + point->move_to(x,y); feature=new VectorFeature(pos,point); ++count_; } else if (type == shape_io::shape_pointz) { - coord c; - shape_.shp().read_coord(c); + double x=shape_.shp().read_double(); + double y=shape_.shp().read_double(); + double z=shape_.shp().read_double(); geometry_ptr point(new point_impl(-1)); - point->move_to(c.x,c.y); + point->move_to(x,y); feature=new VectorFeature(pos,point); ++count_; } diff --git a/src/shape/shape_index_featureset.cc b/src/shape/shape_index_featureset.cc index 3850c94f5..37661d434 100644 --- a/src/shape/shape_index_featureset.cc +++ b/src/shape/shape_index_featureset.cc @@ -55,49 +55,49 @@ Feature* ShapeIndexFeatureset::next() int type=shape_.type(); if (type==shape_io::shape_point) { - coord2d c; - shape_.shp().read_coord(c); - + double x=shape_.shp().read_double(); + double y=shape_.shp().read_double(); geometry_ptr point(new point_impl(-1)); - point->move_to(c.x,c.y); - f=new VectorFeature(pos,point); + point->move_to(x,y); + f=new VectorFeature(shape_.id_,point); ++count_; } else if (type == shape_io::shape_pointz) { - coord c; - shape_.shp().read_coord(c); + double x=shape_.shp().read_double(); + double y=shape_.shp().read_double(); + double z=shape_.shp().read_double(); geometry_ptr point(new point_impl(-1)); - point->move_to(c.x,c.y); - f=new VectorFeature(pos,point); + point->move_to(x,y); + f=new VectorFeature(shape_.id_,point); ++count_; } else { while(!filter_.pass(shape_.current_extent()) && - itr_!=ids_.end()) - { + itr_!=ids_.end()) + { pos=*itr_++; shape_.move_to(pos); - } - + } + switch (type) { - case shape_io::shape_polyline: - { - geometry_ptr line = shape_.read_polyline(); - f=new VectorFeature(pos,line); + case shape_io::shape_polyline: + { + geometry_ptr line = shape_.read_polyline(); + f=new VectorFeature(shape_.id_,line); ++count_; - break; - - } - case shape_io::shape_polygon: - { - geometry_ptr poly = shape_.read_polygon(); - f=new VectorFeature(pos,poly); + break; + } + case shape_io::shape_polygon: + { + + geometry_ptr poly = shape_.read_polygon(); + f=new VectorFeature(shape_.id_,poly); ++count_; - break; - } + break; + } } if (0) { diff --git a/src/shape/shape_io.cc b/src/shape/shape_io.cc index 00be02d22..8cb3419f9 100644 --- a/src/shape/shape_io.cc +++ b/src/shape/shape_io.cc @@ -21,11 +21,14 @@ #include "shape_io.hh" #include "shape.hh" + const std::string shape_io::SHP = ".shp"; const std::string shape_io::DBF = ".dbf"; shape_io::shape_io(const std::string& shape_name) - : type_(shape_null) + : type_(shape_null), + reclength_(0), + id_(0) { bool ok = (shp_.open(shape_name + SHP) && dbf_.open(shape_name + DBF)); @@ -45,9 +48,10 @@ shape_io::~shape_io() void shape_io::move_to (int pos) { shp_.seek(pos); - int id = shp_.read_xdr_integer(); - int reclength_ = shp_.read_xdr_integer(); + id_ = shp_.read_xdr_integer(); + reclength_ = shp_.read_xdr_integer(); type_ = shp_.read_ndr_integer(); + if (type_ != shape_point) { shp_.read_envelope(cur_extent_); @@ -80,53 +84,75 @@ dbf_file& shape_io::dbf() return dbf_; } -mapnik::geometry_ptr shape_io::read_polyline() -{ - int num_parts=shp_.read_ndr_integer(); - int num_points=shp_.read_ndr_integer(); - std::vector parts(num_parts);; - for (int i=0;i > ar(num_points); - shp_.read_coords(ar); +geometry_ptr shape_io::read_polyline() +{ + shape_record record(reclength_*2-36); + shp_.read_record(record); + int num_parts=record.read_ndr_integer(); + int num_points=record.read_ndr_integer(); geometry_ptr line(new line_string_impl(-1)); - - for (int k=0;kmove_to(ar[start].x,ar[start].y); - for (int j=start+1;jline_to(ar[j].x,ar[j].y); - } + record.skip(4); + double x=record.read_double(); + double y=record.read_double(); + line->move_to(x,y); + for (int i=1;iline_to(x,y); + } + } + else + { + std::vector parts(num_parts); + for (int i=0;imove_to(x,y); + + for (int j=start+1;jline_to(x,y); + } + } } return line; } -mapnik::geometry_ptr shape_io::read_polygon() +geometry_ptr shape_io::read_polygon() { - int num_parts=shp_.read_ndr_integer(); - int num_points=shp_.read_ndr_integer(); + shape_record record(reclength_*2-36); + shp_.read_record(record); + int num_parts=record.read_ndr_integer(); + int num_points=record.read_ndr_integer(); std::vector parts(num_parts); geometry_ptr poly(new polygon_impl(-1)); + for (int i=0;i > ar(num_points); - shp_.read_coords(ar); - - for (int k=0;kmove_to(ar[start].x,ar[start].y); + double x=record.read_double(); + double y=record.read_double(); + poly->move_to(x,y); for (int j=start+1;jline_to(ar[j].x,ar[j].y); + x=record.read_double(); + y=record.read_double(); + poly->line_to(x,y); } - - poly->line_to(ar[start].x,ar[start].y); } return poly; } + diff --git a/src/shape/shape_io.hh b/src/shape/shape_io.hh index b382d083d..6867d5a1c 100644 --- a/src/shape/shape_io.hh +++ b/src/shape/shape_io.hh @@ -34,7 +34,9 @@ struct shape_io shape_file shp_; shape_file shx_; dbf_file dbf_; - int type_; + unsigned type_; + unsigned reclength_; + unsigned id_; Envelope cur_extent_; public: @@ -65,10 +67,12 @@ public: void move_to(int id); int type() const; const Envelope& current_extent() const; + geometry_ptr read_polyline(); geometry_ptr read_polygon(); - geometry_ptr read_multipolygon(); + //geometry_ptr read_multipolygon(shape_record& record); private: + //void read_record(const shape_record& record); // no copying shape_io(const shape_io&); shape_io& operator=(const shape_io&); diff --git a/src/shape/shapefile.cc b/src/shape/shapefile.cc index 35e1d283b..43d73820b 100644 --- a/src/shape/shapefile.cc +++ b/src/shape/shapefile.cc @@ -23,11 +23,10 @@ shape_file::shape_file() {} shape_file::shape_file(const std::string& file_name) { - file_.rdbuf()->pubsetbuf(buff_,buffer_size); + //file_.rdbuf()->pubsetbuf(buff_,buffer_size); file_.open(file_name.c_str(),std::ios::in|std::ios::binary); } - shape_file::~shape_file() { if (file_ && file_.is_open()) @@ -37,7 +36,7 @@ shape_file::~shape_file() bool shape_file::open(const std::string& file_name) { - file_.rdbuf()->pubsetbuf(buff_,buffer_size); + //file_.rdbuf()->pubsetbuf(buff_,buffer_size); file_.open(file_name.c_str(),std::ios::in | std::ios::binary); return file_?true:false; } diff --git a/src/shape/shapefile.hh b/src/shape/shapefile.hh index d29f172b2..0151d6019 100644 --- a/src/shape/shapefile.hh +++ b/src/shape/shapefile.hh @@ -26,25 +26,78 @@ using namespace mapnik; -class shape_file +struct shape_record { - // POD structure to hold shape record - struct shape_record - { - unsigned char* data; - size_t size; - explicit shape_record(size_t size) - : data(static_cast(::operator new(sizeof(unsigned char)*size))), - size(size) {} - ~shape_record() - { - ::operator delete(data); - } - }; + char* data; + size_t size; + size_t pos; + explicit shape_record(size_t size) + : data(static_cast(::operator new(sizeof(char)*size))), + size(size), + pos(0) {} + char* rawdata() + { + return &data[0]; + } + void skip(unsigned n) + { + pos+=n; + } + int read_ndr_integer() + { + int val=(data[pos] & 0xff) | + (data[pos+1] & 0xff) << 8 | + (data[pos+2] & 0xff) << 16 | + (data[pos+3] & 0xff) << 24; + pos+=4; + return val; + } + + int read_xdr_integer() + { + int val=(data[pos] & 0xff) << 24 | + (data[pos+1] & 0xff) << 16 | + (data[pos+2] & 0xff) << 8 | + (data[pos+3] & 0xff); + pos+=4; + return val; + } + + double read_double() + { + double val; +#ifndef WORDS_BIGENDIAN + std::memcpy(&val,&data[pos],8); +#else + long long bits = ((long long)data[pos] & 0xff) | + ((long long)data[pos+1] & 0xff) << 8 | + ((long long)data[pos+2] & 0xff) << 16 | + ((long long)data[pos+3] & 0xff) << 24 | + ((long long)data[pos+4] & 0xff) << 32 | + ((long long)data[pos+5] & 0xff) << 40 | + ((long long)data[pos+6] & 0xff) << 48 | + ((long long)data[pos+7] & 0xff) << 56 ; + std::memcpy(&val,&bits,8); +#endif + pos+=8; + return val; + } + long remains() + { + return (size-pos); + } + ~shape_record() + { + ::operator delete(data); + } +}; + +class shape_file +{ std::ifstream file_; - static const int buffer_size = 16; - char buff_[buffer_size]; + //static const int buffer_size = 16; + //char buff_[buffer_size]; public: shape_file(); shape_file(const std::string& file_name); @@ -53,60 +106,46 @@ public: bool is_open(); void close(); - template - inline void shape_file::read_coord(coord& coord) + inline void shape_file::read_record(shape_record& rec) { -#ifndef WORDS_BIGENDIAN - file_.read(reinterpret_cast(&coord),sizeof(coord)); -#else -#error "TODO: big-endian" -#endif - } - - template - inline void shape_file::read_coords(coord_array &ar) - { -#ifndef WORDS_BIGENDIAN - file_.read(reinterpret_cast(&ar[0]),sizeof(T)*ar.size()); -#else -#error "TODO: big-endian" -#endif - + file_.read(rec.rawdata(),rec.size); } inline int read_xdr_integer() { -#ifndef WORDS_BIGENDIAN char b[4]; file_.read(b, 4); return b[3] & 0xffu | (b[2] & 0xffu) << 8 | (b[1] & 0xffu) << 16 | (b[0] & 0xffu) << 24; -#else -#error "TODO: big-endian " -#endif } inline int read_ndr_integer() { -#ifndef WORDS_BIGENDIAN char b[4]; file_.read(b,4); return b[0]&0xffu | (b[1]&0xffu) << 8 | (b[2]&0xffu) << 16 | (b[3]&0xffu) << 24; -#else -#error "TODO: big-endian " -#endif } inline double read_double() { -#ifndef WORDS_BIGENDIAN double val; - file_.read(reinterpret_cast(&val),sizeof(val)); - return val; +#ifndef WORDS_BIGENDIAN + file_.read(reinterpret_cast(&val),8); #else -#error "TODO: big-endian " + char b[8]; + file_.read(b,8); + long long bits = ((long long)b[0] & 0xff) | + ((long long)b[1] & 0xff) << 8 | + ((long long)b[2] & 0xff) << 16 | + ((long long)b[3] & 0xff) << 24 | + ((long long)b[4] & 0xff) << 32 | + ((long long)b[5] & 0xff) << 40 | + ((long long)b[6] & 0xff) << 48 | + ((long long)b[7] & 0xff) << 56 ; + memcpy(&val,&bits,8); #endif + return val; } inline void read_envelope(Envelope& envelope) @@ -114,23 +153,24 @@ public: #ifndef WORDS_BIGENDIAN file_.read(reinterpret_cast(&envelope),sizeof(envelope)); #else -#error "TODO: big-endian" + double minx=read_double(); + double miny=read_double(); + double maxx=read_double(); + double maxy=read_double(); + envelope.init(minx,miny,maxx,maxy); #endif } - inline void skip(int bytes) { file_.seekg(bytes,std::ios::cur); } - inline void rewind() { seek(100); } - inline void seek(long pos) { file_.seekg(pos,std::ios::beg); diff --git a/src/shape/shp_index.cc b/src/shape/shp_index.cc index 4e9f652ff..9b89c111c 100644 --- a/src/shape/shp_index.cc +++ b/src/shape/shp_index.cc @@ -29,8 +29,8 @@ void shp_index::query(const filterT& filter,std::ifstream& file,std::se template void shp_index::query_node(const filterT& filter,std::ifstream& file,std::set& ids) { - int offset=read_ndr_integer(file); + Envelope node_ext; read_envelope(file,node_ext); @@ -62,7 +62,7 @@ int shp_index::read_ndr_integer(std::ifstream& file) { char b[4]; file.read(b,4); - return b[0]&0xff | (b[1]&0xff)<<8 | (b[2]&0xff)<<16 | (b[3]&0xff)<<24; + return (b[0]&0xff) | (b[1]&0xff)<<8 | (b[2]&0xff)<<16 | (b[3]&0xff)<<24; }