#include "XBaseParser.h" #include #include #if defined(_MSC_VER) || defined(__MINGW32__) #include #include #else #include #endif #include #include namespace ESRIShape { void XBaseHeader::print() { osg::notify(osg::INFO) << "VersionNumber = " << (int) _versionNumber << std::endl << "LastUpdate = " << 1900 + (int) _lastUpdate[0] << "/" << (int) _lastUpdate[1] << "/" << (int) _lastUpdate[2] << std::endl << "NumRecord = " << _numRecord << std::endl << "HeaderLength = " << _headerLength << std::endl << "RecordLength = " << _recordLength << std::endl; } bool XBaseHeader::read(int fd) { int nbytes = 0; if ((nbytes = ::read( fd, &_versionNumber, sizeof(_versionNumber))) <= 0) return false; if ((nbytes = ::read( fd, &_lastUpdate, sizeof(_lastUpdate))) <= 0) return false; if ((nbytes = ::read( fd, &_numRecord, sizeof(_numRecord))) <= 0) return false; if ((nbytes = ::read( fd, &_headerLength, sizeof(_headerLength))) <= 0) return false; if ((nbytes = ::read( fd, &_recordLength, sizeof(_recordLength))) <= 0) return false; if ((nbytes = ::read( fd, &_reserved, sizeof(_reserved))) <= 0) return false; if ((nbytes = ::read( fd, &_incompleteTransaction, sizeof(_incompleteTransaction))) <= 0) return false; if ((nbytes = ::read( fd, &_encryptionFlag, sizeof(_encryptionFlag))) <= 0) return false; if ((nbytes = ::read( fd, &_freeRecordThread, sizeof(_freeRecordThread))) <= 0) return false; if ((nbytes = ::read( fd, &_reservedMultiUser, sizeof(_reservedMultiUser))) <= 0) return false; if ((nbytes = ::read( fd, &_mdxflag, sizeof(_mdxflag))) <= 0) return false; if ((nbytes = ::read( fd, &_languageDriver, sizeof(_languageDriver))) <= 0) return false; if ((nbytes = ::read( fd, &_reserved2, sizeof(_reserved2))) <= 0) return false; return true; } void XBaseFieldDescriptor::print() { osg::notify(osg::INFO) << "name = " << _name << std::endl << "type = " << _fieldType << std::endl << "length = " << (int) _fieldLength << std::endl << "decimalCount = " << (int) _decimalCount << std::endl << "workAreaID = " << (int) _workAreaID << std::endl << "setFieldFlag = " << (int) _setFieldFlag << std::endl << "indexFieldFlag = " << (int) _indexFieldFlag << std::endl; } bool XBaseFieldDescriptor::read(int fd) { int nbytes = 0; if ((nbytes = ::read( fd, &_name, sizeof(_name))) <= 0) return false; if ((nbytes = ::read( fd, &_fieldType, sizeof(_fieldType))) <= 0) return false; if ((nbytes = ::read( fd, &_fieldDataAddress, sizeof(_fieldDataAddress))) <= 0) return false; if ((nbytes = ::read( fd, &_fieldLength, sizeof(_fieldLength))) <= 0) return false; if ((nbytes = ::read( fd, &_decimalCount, sizeof(_decimalCount))) <= 0) return false; if ((nbytes = ::read( fd, &_reservedMultiUser, sizeof(_reservedMultiUser))) <= 0) return false; if ((nbytes = ::read( fd, &_workAreaID, sizeof(_workAreaID))) <= 0) return false; if ((nbytes = ::read( fd, &_reservedMultiUser2, sizeof(_reservedMultiUser2))) <= 0) return false; if ((nbytes = ::read( fd, &_setFieldFlag, sizeof(_setFieldFlag))) <= 0) return false; if ((nbytes = ::read( fd, &_reserved, sizeof(_reserved))) <= 0) return false; if ((nbytes = ::read( fd, &_indexFieldFlag, sizeof(_indexFieldFlag))) <= 0) return false; return true; } XBaseParser::XBaseParser(const std::string fileName): _valid(false) { int fd = 0; if (fileName.empty() == false) { #ifdef WIN32 if( (fd = open( fileName.c_str(), O_RDONLY | O_BINARY )) <= 0 ) #else if( (fd = ::open( fileName.c_str(), O_RDONLY )) <= 0 ) #endif { perror( fileName.c_str() ); return ; } } _valid = parse(fd); } bool XBaseParser::parse(int fd) { int nbytes; XBaseHeader _xBaseHeader; std::vector _xBaseFieldDescriptorList; XBaseFieldDescriptor _xBaseFieldDescriptorTmp; // ** read the header if (_xBaseHeader.read(fd) == false) return false; // _xBaseHeader.print(); // ** read field descriptor bool fieldDescriptorDone = false; Byte nullTerminator; while (fieldDescriptorDone == false) { // ** store the field descriptor if (_xBaseFieldDescriptorTmp.read(fd) == false) return false; _xBaseFieldDescriptorList.push_back(_xBaseFieldDescriptorTmp); // _xBaseFieldDescriptorTmp.print(); // ** check the terminator if ((nbytes = ::read( fd, &nullTerminator, sizeof(nullTerminator))) <= 0) return false; if (nullTerminator == 0x0D) fieldDescriptorDone = true; else ::lseek( fd, -1, SEEK_CUR); } // ** move to the end of the Header ::lseek( fd, _xBaseHeader._headerLength + 1, SEEK_SET); // ** reserve AttributeListList _shapeAttributeListList.reserve(_xBaseHeader._numRecord); // ** read each record and store them in the ShapeAttributeListList char* record = new char[_xBaseHeader._recordLength]; std::vector::iterator it, end = _xBaseFieldDescriptorList.end(); for (Integer i = 0; i < _xBaseHeader._numRecord; ++i) { if ((nbytes = ::read( fd, record, _xBaseHeader._recordLength)) <= 0) return false; char * recordPtr = record; osgSim::ShapeAttributeList * shapeAttributeList = new osgSim::ShapeAttributeList; shapeAttributeList->reserve(_xBaseFieldDescriptorList.size()); for (it = _xBaseFieldDescriptorList.begin(); it != end; ++it) { switch (it->_fieldType) { case 'C': { char* str = new char[it->_fieldLength + 1]; memcpy(str, recordPtr, it->_fieldLength); str[it->_fieldLength] = 0; shapeAttributeList->push_back(osgSim::ShapeAttribute((const char *) it->_name, (char*) str)); delete [] str; break; } case 'N': { char* number = new char[it->_fieldLength + 1]; memcpy(number, recordPtr, it->_fieldLength); number[it->_fieldLength] = 0; shapeAttributeList->push_back(osgSim::ShapeAttribute((const char *) it->_name, (int) atoi(number))); delete [] number; break; } case 'I': { int number; memcpy(&number, record, it->_fieldLength); shapeAttributeList->push_back(osgSim::ShapeAttribute((const char *) it->_name, (int) number)); break; } case 'O': { double number; memcpy(&number, record, it->_fieldLength); shapeAttributeList->push_back(osgSim::ShapeAttribute((const char *) it->_name, (double) number)); break; } default: { osg::notify(osg::WARN) << "ESRIShape::XBaseParser : record type " << it->_fieldType << "not supported, skipped" << std::endl; shapeAttributeList->push_back(osgSim::ShapeAttribute((const char *) it->_name, (double) 0)); break; } } recordPtr += it->_fieldLength; } _shapeAttributeListList.push_back(shapeAttributeList); } delete [] record; close (fd); return true; } }