portable i/o (almost)
This commit is contained in:
parent
6fe5294257
commit
e124e75441
9 changed files with 221 additions and 161 deletions
|
@ -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<std::string>(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="<<desc.name_<<std::endl;
|
||||
fields_.push_back(desc);
|
||||
}
|
||||
record_length_=offset;
|
||||
if (record_length_>0)
|
||||
{
|
||||
record_=new char[record_length_];
|
||||
record_=static_cast<char*>(::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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -23,8 +23,6 @@
|
|||
#include <string>
|
||||
#include <fstream>
|
||||
#include <cassert>
|
||||
//#include <iostream>
|
||||
|
||||
|
||||
#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
|
||||
|
|
|
@ -47,19 +47,20 @@ Feature* ShapeFeatureset<filterT>::next()
|
|||
|
||||
if (type == shape_io::shape_point)
|
||||
{
|
||||
coord<double,2> 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<double,3> 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_;
|
||||
}
|
||||
|
|
|
@ -55,49 +55,49 @@ Feature* ShapeIndexFeatureset<filterT>::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<double,3> 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)
|
||||
{
|
||||
|
|
|
@ -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<int> parts(num_parts);;
|
||||
for (int i=0;i<num_parts;++i)
|
||||
{
|
||||
parts[i]=shp_.read_ndr_integer();
|
||||
}
|
||||
|
||||
coord_array<coord<double,2> > 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;k<num_parts;++k)
|
||||
|
||||
if (num_parts == 1)
|
||||
{
|
||||
int start=parts[k];
|
||||
int end;
|
||||
if (k==num_parts-1)
|
||||
end=num_points;
|
||||
else
|
||||
end=parts[k+1];
|
||||
line->move_to(ar[start].x,ar[start].y);
|
||||
for (int j=start+1;j<end;++j)
|
||||
{
|
||||
line->line_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;i<num_points;++i)
|
||||
{
|
||||
x=record.read_double();
|
||||
y=record.read_double();
|
||||
line->line_to(x,y);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<int> parts(num_parts);
|
||||
for (int i=0;i<num_parts;++i)
|
||||
{
|
||||
parts[i]=record.read_ndr_integer();
|
||||
}
|
||||
|
||||
int start,end;
|
||||
for (int k=0;k<num_parts;++k)
|
||||
{
|
||||
start=parts[k];
|
||||
if (k==num_parts-1)
|
||||
end=num_points;
|
||||
else
|
||||
end=parts[k+1];
|
||||
|
||||
double x=record.read_double();
|
||||
double y=record.read_double();
|
||||
line->move_to(x,y);
|
||||
|
||||
for (int j=start+1;j<end;++j)
|
||||
{
|
||||
x=record.read_double();
|
||||
y=record.read_double();
|
||||
line->line_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<int> parts(num_parts);
|
||||
geometry_ptr poly(new polygon_impl(-1));
|
||||
|
||||
for (int i=0;i<num_parts;++i)
|
||||
{
|
||||
parts[i]=shp_.read_ndr_integer();
|
||||
parts[i]=record.read_ndr_integer();
|
||||
}
|
||||
|
||||
coord_array<coord<double,2> > ar(num_points);
|
||||
shp_.read_coords(ar);
|
||||
|
||||
for (int k=0;k<num_parts;++k)
|
||||
for (int k=0;k<num_parts;k++)
|
||||
{
|
||||
int start=parts[k];
|
||||
int end;
|
||||
|
@ -138,14 +164,17 @@ mapnik::geometry_ptr shape_io::read_polygon()
|
|||
{
|
||||
end=parts[k+1];
|
||||
}
|
||||
poly->move_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;j<end;j++)
|
||||
{
|
||||
poly->line_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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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<double> cur_extent_;
|
||||
|
||||
public:
|
||||
|
@ -65,10 +67,12 @@ public:
|
|||
void move_to(int id);
|
||||
int type() const;
|
||||
const Envelope<double>& 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&);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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<unsigned char*>(::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<char*>(::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 <typename T,int dim>
|
||||
inline void shape_file::read_coord(coord<T,dim>& coord)
|
||||
inline void shape_file::read_record(shape_record& rec)
|
||||
{
|
||||
#ifndef WORDS_BIGENDIAN
|
||||
file_.read(reinterpret_cast<char*>(&coord),sizeof(coord));
|
||||
#else
|
||||
#error "TODO: big-endian"
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void shape_file::read_coords(coord_array<T> &ar)
|
||||
{
|
||||
#ifndef WORDS_BIGENDIAN
|
||||
file_.read(reinterpret_cast<char*>(&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<char*>(&val),sizeof(val));
|
||||
return val;
|
||||
#ifndef WORDS_BIGENDIAN
|
||||
file_.read(reinterpret_cast<char*>(&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<double>& envelope)
|
||||
|
@ -114,23 +153,24 @@ public:
|
|||
#ifndef WORDS_BIGENDIAN
|
||||
file_.read(reinterpret_cast<char*>(&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);
|
||||
|
|
|
@ -29,8 +29,8 @@ void shp_index<filterT>::query(const filterT& filter,std::ifstream& file,std::se
|
|||
template <typename filterT>
|
||||
void shp_index<filterT>::query_node(const filterT& filter,std::ifstream& file,std::set<int>& ids)
|
||||
{
|
||||
|
||||
int offset=read_ndr_integer(file);
|
||||
|
||||
Envelope<double> node_ext;
|
||||
read_envelope(file,node_ext);
|
||||
|
||||
|
@ -62,7 +62,7 @@ int shp_index<filterT>::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;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue