portable i/o (almost)

This commit is contained in:
Artem Pavlenko 2005-03-29 19:18:59 +00:00
parent 6fe5294257
commit e124e75441
9 changed files with 221 additions and 161 deletions

View file

@ -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;
}

View file

@ -23,8 +23,6 @@
#include <string>
#include <fstream>
#include <cassert>
//#include <iostream>
#include "mapnik.hh"
@ -32,7 +30,6 @@ using namespace mapnik;
struct field_descriptor
{
public:
int index_;
std::string name_;
char type_;
@ -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

View file

@ -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_;
}

View file

@ -55,21 +55,21 @@ 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
@ -86,15 +86,15 @@ Feature* ShapeIndexFeatureset<filterT>::next()
case shape_io::shape_polyline:
{
geometry_ptr line = shape_.read_polyline();
f=new VectorFeature(pos,line);
f=new VectorFeature(shape_.id_,line);
++count_;
break;
}
case shape_io::shape_polygon:
{
geometry_ptr poly = shape_.read_polygon();
f=new VectorFeature(pos,poly);
f=new VectorFeature(shape_.id_,poly);
++count_;
break;
}

View file

@ -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()
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);
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));
if (num_parts == 1)
{
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)
{
int start=parts[k];
int end;
start=parts[k];
if (k==num_parts-1)
end=num_points;
else
end=parts[k+1];
line->move_to(ar[start].x,ar[start].y);
double x=record.read_double();
double y=record.read_double();
line->move_to(x,y);
for (int j=start+1;j<end;++j)
{
line->line_to(ar[j].x,ar[j].y);
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;
}

View file

@ -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&);

View file

@ -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;
}

View file

@ -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;
char* data;
size_t size;
size_t pos;
explicit shape_record(size_t size)
: data(static_cast<unsigned char*>(::operator new(sizeof(unsigned char)*size))),
size(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);

View file

@ -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;
}