Download include/colmap/lib/FLANN/util/serialization.h from camenduru/ceres-solver: direct link, hf CLI and curl.
- Browser
- Download file 20.2 kB
-
https://huggingface.co/camenduru/ceres-solver/resolve/main/include/colmap/lib/FLANN/util/serialization.h
- Command line
-
hf download hf://camenduru/ceres-solver/include/colmap/lib/FLANN/util/serialization.h
-
curl -L -o serialization.h https://huggingface.co/camenduru/ceres-solver/resolve/main/include/colmap/lib/FLANN/util/serialization.h
20.2 kB
| namespace flann | |
| { | |
| struct IndexHeaderStruct { | |
| char signature[24]; | |
| char version[16]; | |
| flann_datatype_t data_type; | |
| flann_algorithm_t index_type; | |
| size_t rows; | |
| size_t cols; | |
| size_t compression; | |
| size_t first_block_size; | |
| }; | |
| namespace serialization | |
| { | |
| struct access | |
| { | |
| template<typename Archive, typename T> | |
| static inline void serialize(Archive& ar, T& type) | |
| { | |
| type.serialize(ar); | |
| } | |
| }; | |
| template<typename Archive, typename T> | |
| inline void serialize(Archive& ar, T& type) | |
| { | |
| access::serialize(ar,type); | |
| } | |
| template<typename T> | |
| struct Serializer | |
| { | |
| template<typename InputArchive> | |
| static inline void load(InputArchive& ar, T& val) | |
| { | |
| serialization::serialize(ar,val); | |
| } | |
| template<typename OutputArchive> | |
| static inline void save(OutputArchive& ar, const T& val) | |
| { | |
| serialization::serialize(ar,const_cast<T&>(val)); | |
| } | |
| }; | |
| // declare serializers for simple types | |
| BASIC_TYPE_SERIALIZER(char); | |
| BASIC_TYPE_SERIALIZER(unsigned char); | |
| BASIC_TYPE_SERIALIZER(short); | |
| BASIC_TYPE_SERIALIZER(unsigned short); | |
| BASIC_TYPE_SERIALIZER(int); | |
| BASIC_TYPE_SERIALIZER(unsigned int); | |
| BASIC_TYPE_SERIALIZER(long); | |
| BASIC_TYPE_SERIALIZER(unsigned long); | |
| BASIC_TYPE_SERIALIZER(unsigned long long); | |
| BASIC_TYPE_SERIALIZER(float); | |
| BASIC_TYPE_SERIALIZER(double); | |
| BASIC_TYPE_SERIALIZER(bool); | |
| // unsigned __int64 ~= unsigned long long | |
| // Will throw error on VS2013 | |
| BASIC_TYPE_SERIALIZER(unsigned __int64); | |
| // serializer for std::vector | |
| template<typename T> | |
| struct Serializer<std::vector<T> > | |
| { | |
| template<typename InputArchive> | |
| static inline void load(InputArchive& ar, std::vector<T>& val) | |
| { | |
| size_t size; | |
| ar & size; | |
| val.resize(size); | |
| for (size_t i=0;i<size;++i) { | |
| ar & val[i]; | |
| } | |
| } | |
| template<typename OutputArchive> | |
| static inline void save(OutputArchive& ar, const std::vector<T>& val) | |
| { | |
| ar & val.size(); | |
| for (size_t i=0;i<val.size();++i) { | |
| ar & val[i]; | |
| } | |
| } | |
| }; | |
| // serializer for std::vector | |
| template<typename K, typename V> | |
| struct Serializer<std::map<K,V> > | |
| { | |
| template<typename InputArchive> | |
| static inline void load(InputArchive& ar, std::map<K,V>& map_val) | |
| { | |
| size_t size; | |
| ar & size; | |
| for (size_t i = 0; i < size; ++i) | |
| { | |
| K key; | |
| ar & key; | |
| V value; | |
| ar & value; | |
| map_val[key] = value; | |
| } | |
| } | |
| template<typename OutputArchive> | |
| static inline void save(OutputArchive& ar, const std::map<K,V>& map_val) | |
| { | |
| ar & map_val.size(); | |
| for (typename std::map<K,V>::const_iterator i=map_val.begin(); i!=map_val.end(); ++i) { | |
| ar & i->first; | |
| ar & i->second; | |
| } | |
| } | |
| }; | |
| template<typename T> | |
| struct Serializer<T*> | |
| { | |
| template<typename InputArchive> | |
| static inline void load(InputArchive& ar, T*& val) | |
| { | |
| ar.load(val); | |
| } | |
| template<typename OutputArchive> | |
| static inline void save(OutputArchive& ar, T* const& val) | |
| { | |
| ar.save(val); | |
| } | |
| }; | |
| template<typename T, int N> | |
| struct Serializer<T[N]> | |
| { | |
| template<typename InputArchive> | |
| static inline void load(InputArchive& ar, T (&val)[N]) | |
| { | |
| ar.load(val); | |
| } | |
| template<typename OutputArchive> | |
| static inline void save(OutputArchive& ar, T const (&val)[N]) | |
| { | |
| ar.save(val); | |
| } | |
| }; | |
| struct binary_object | |
| { | |
| void const * ptr_; | |
| size_t size_; | |
| binary_object( void * const ptr, size_t size) : | |
| ptr_(ptr), | |
| size_(size) | |
| {} | |
| binary_object(const binary_object & rhs) : | |
| ptr_(rhs.ptr_), | |
| size_(rhs.size_) | |
| {} | |
| binary_object & operator=(const binary_object & rhs) { | |
| ptr_ = rhs.ptr_; | |
| size_ = rhs.size_; | |
| return *this; | |
| } | |
| }; | |
| inline const binary_object make_binary_object(/* const */ void * t, size_t size){ | |
| return binary_object(t, size); | |
| } | |
| template<> | |
| struct Serializer<const binary_object> | |
| { | |
| template<typename InputArchive> | |
| static inline void load(InputArchive& ar, const binary_object& b) | |
| { | |
| ar.load_binary(const_cast<void *>(b.ptr_), b.size_); | |
| } | |
| template<typename OutputArchive> | |
| static inline void save(OutputArchive& ar, const binary_object& b) | |
| { | |
| ar.save_binary(b.ptr_, b.size_); | |
| } | |
| }; | |
| template<> | |
| struct Serializer<binary_object> | |
| { | |
| template<typename InputArchive> | |
| static inline void load(InputArchive& ar, binary_object& b) | |
| { | |
| ar.load_binary(const_cast<void *>(b.ptr_), b.size_); | |
| } | |
| template<typename OutputArchive> | |
| static inline void save(OutputArchive& ar, const binary_object& b) | |
| { | |
| ar.save_binary(b.ptr_, b.size_); | |
| } | |
| }; | |
| template <bool C_> | |
| struct bool_ { | |
| static const bool value = C_; | |
| typedef bool value_type; | |
| }; | |
| class ArchiveBase | |
| { | |
| public: | |
| void* getObject() { return object_; } | |
| void setObject(void* object) { object_ = object; } | |
| private: | |
| void* object_; | |
| }; | |
| template<typename Archive> | |
| class InputArchive : public ArchiveBase | |
| { | |
| protected: | |
| InputArchive() {}; | |
| public: | |
| typedef bool_<true> is_loading; | |
| typedef bool_<false> is_saving; | |
| template<typename T> | |
| Archive& operator& (T& val) | |
| { | |
| Serializer<T>::load(*static_cast<Archive*>(this),val); | |
| return *static_cast<Archive*>(this); | |
| } | |
| }; | |
| template<typename Archive> | |
| class OutputArchive : public ArchiveBase | |
| { | |
| protected: | |
| OutputArchive() {}; | |
| public: | |
| typedef bool_<false> is_loading; | |
| typedef bool_<true> is_saving; | |
| template<typename T> | |
| Archive& operator& (const T& val) | |
| { | |
| Serializer<T>::save(*static_cast<Archive*>(this),val); | |
| return *static_cast<Archive*>(this); | |
| } | |
| }; | |
| class SizeArchive : public OutputArchive<SizeArchive> | |
| { | |
| size_t size_; | |
| public: | |
| SizeArchive() : size_(0) | |
| { | |
| } | |
| template<typename T> | |
| void save(const T& val) | |
| { | |
| size_ += sizeof(val); | |
| } | |
| template<typename T> | |
| void save_binary(T* ptr, size_t size) | |
| { | |
| size_ += size; | |
| } | |
| void reset() | |
| { | |
| size_ = 0; | |
| } | |
| size_t size() | |
| { | |
| return size_; | |
| } | |
| }; | |
| // | |
| //class PrintArchive : public OutputArchive<PrintArchive> | |
| //{ | |
| //public: | |
| // template<typename T> | |
| // void save(const T& val) | |
| // { | |
| // std::cout << val << std::endl; | |
| // } | |
| // | |
| // template<typename T> | |
| // void save_binary(T* ptr, size_t size) | |
| // { | |
| // std::cout << "<binary object>" << std::endl; | |
| // } | |
| //}; | |
| class SaveArchive : public OutputArchive<SaveArchive> | |
| { | |
| /** | |
| * Based on blockStreaming_doubleBuffer code at: | |
| * https://github.com/Cyan4973/lz4/blob/master/examples/blockStreaming_doubleBuffer.c | |
| */ | |
| FILE* stream_; | |
| bool own_stream_; | |
| char *buffer_; | |
| size_t offset_; | |
| int first_block_; | |
| char *buffer_blocks_; | |
| char *compressed_buffer_; | |
| LZ4_streamHC_t lz4Stream_body; | |
| LZ4_streamHC_t* lz4Stream; | |
| void initBlock() | |
| { | |
| // Alloc the space for both buffer blocks (each compressed block | |
| // references the previous) | |
| buffer_ = buffer_blocks_ = (char *)malloc(BLOCK_BYTES*2); | |
| compressed_buffer_ = (char *)malloc(LZ4_COMPRESSBOUND(BLOCK_BYTES) + sizeof(size_t)); | |
| if (buffer_ == NULL || compressed_buffer_ == NULL) { | |
| throw FLANNException("Error allocating compression buffer"); | |
| } | |
| // Init the LZ4 stream | |
| lz4Stream = &lz4Stream_body; | |
| LZ4_resetStreamHC(lz4Stream, 9); | |
| first_block_ = true; | |
| offset_ = 0; | |
| } | |
| void flushBlock() | |
| { | |
| size_t compSz = 0; | |
| // Handle header | |
| if (first_block_) { | |
| // Copy & set the header | |
| IndexHeaderStruct *head = (IndexHeaderStruct *)buffer_; | |
| size_t headSz = sizeof(IndexHeaderStruct); | |
| assert(head->compression == 0); | |
| head->compression = 1; // Bool now, enum later | |
| // Do the compression for the block | |
| compSz = LZ4_compress_HC_continue( | |
| lz4Stream, buffer_+headSz, compressed_buffer_+headSz, offset_-headSz, | |
| LZ4_COMPRESSBOUND(BLOCK_BYTES)); | |
| if(compSz <= 0) { | |
| throw FLANNException("Error compressing (first block)"); | |
| } | |
| // Handle header | |
| head->first_block_size = compSz; | |
| memcpy(compressed_buffer_, buffer_, headSz); | |
| compSz += headSz; | |
| first_block_ = false; | |
| } else { | |
| size_t headSz = sizeof(compSz); | |
| // Do the compression for the block | |
| compSz = LZ4_compress_HC_continue( | |
| lz4Stream, buffer_, compressed_buffer_+headSz, offset_, | |
| LZ4_COMPRESSBOUND(BLOCK_BYTES)); | |
| if(compSz <= 0) { | |
| throw FLANNException("Error compressing"); | |
| } | |
| // Save the size of the compressed block as the header | |
| memcpy(compressed_buffer_, &compSz, headSz); | |
| compSz += headSz; | |
| } | |
| // Write the compressed buffer | |
| fwrite(compressed_buffer_, compSz, 1, stream_); | |
| // Switch the buffer to the *other* block | |
| if (buffer_ == buffer_blocks_) | |
| buffer_ = &buffer_blocks_[BLOCK_BYTES]; | |
| else | |
| buffer_ = buffer_blocks_; | |
| offset_ = 0; | |
| } | |
| void endBlock() | |
| { | |
| // Cleanup memory | |
| free(buffer_blocks_); | |
| buffer_blocks_ = NULL; | |
| buffer_ = NULL; | |
| free(compressed_buffer_); | |
| compressed_buffer_ = NULL; | |
| // Write a '0' size for next block | |
| size_t z = 0; | |
| fwrite(&z, sizeof(z), 1, stream_); | |
| } | |
| public: | |
| SaveArchive(const char* filename) | |
| { | |
| stream_ = fopen(filename, "wb"); | |
| own_stream_ = true; | |
| initBlock(); | |
| } | |
| SaveArchive(FILE* stream) : stream_(stream), own_stream_(false) | |
| { | |
| initBlock(); | |
| } | |
| ~SaveArchive() | |
| { | |
| flushBlock(); | |
| endBlock(); | |
| if (buffer_) { | |
| free(buffer_); | |
| buffer_ = NULL; | |
| } | |
| if (own_stream_) { | |
| fclose(stream_); | |
| } | |
| } | |
| template<typename T> | |
| void save(const T& val) | |
| { | |
| assert(sizeof(val) < BLOCK_BYTES); | |
| if (offset_+sizeof(val) > BLOCK_BYTES) | |
| flushBlock(); | |
| memcpy(buffer_+offset_, &val, sizeof(val)); | |
| offset_ += sizeof(val); | |
| } | |
| template<typename T> | |
| void save(T* const& val) | |
| { | |
| // don't save pointers | |
| //fwrite(&val, sizeof(val), 1, handle_); | |
| } | |
| template<typename T> | |
| void save_binary(T* ptr, size_t size) | |
| { | |
| while (size > BLOCK_BYTES) { | |
| // Flush existing block | |
| flushBlock(); | |
| // Save large chunk | |
| memcpy(buffer_, ptr, BLOCK_BYTES); | |
| offset_ += BLOCK_BYTES; | |
| ptr = ((char *)ptr) + BLOCK_BYTES; | |
| size -= BLOCK_BYTES; | |
| } | |
| // Save existing block if new data will make it too big | |
| if (offset_+size > BLOCK_BYTES) | |
| flushBlock(); | |
| // Copy out requested data | |
| memcpy(buffer_+offset_, ptr, size); | |
| offset_ += size; | |
| } | |
| }; | |
| class LoadArchive : public InputArchive<LoadArchive> | |
| { | |
| /** | |
| * Based on blockStreaming_doubleBuffer code at: | |
| * https://github.com/Cyan4973/lz4/blob/master/examples/blockStreaming_doubleBuffer.c | |
| */ | |
| FILE* stream_; | |
| bool own_stream_; | |
| char *buffer_; | |
| char *ptr_; | |
| char *buffer_blocks_; | |
| char *compressed_buffer_; | |
| LZ4_streamDecode_t lz4StreamDecode_body; | |
| LZ4_streamDecode_t* lz4StreamDecode; | |
| size_t block_sz_; | |
| void decompressAndLoadV10(FILE* stream) | |
| { | |
| buffer_ = NULL; | |
| // Find file size | |
| size_t pos = ftell(stream); | |
| fseek(stream, 0, SEEK_END); | |
| size_t fileSize = ftell(stream)-pos; | |
| fseek(stream, pos, SEEK_SET); | |
| size_t headSz = sizeof(IndexHeaderStruct); | |
| // Read the (compressed) file to a buffer | |
| char *compBuffer = (char *)malloc(fileSize); | |
| if (compBuffer == NULL) { | |
| throw FLANNException("Error allocating file buffer space"); | |
| } | |
| if (fread(compBuffer, fileSize, 1, stream) != 1) { | |
| free(compBuffer); | |
| throw FLANNException("Invalid index file, cannot read from disk (compressed)"); | |
| } | |
| // Extract header | |
| IndexHeaderStruct *head = (IndexHeaderStruct *)(compBuffer); | |
| // Backward compatability | |
| size_t compressedSz = fileSize-headSz; | |
| size_t uncompressedSz = head->first_block_size-headSz; | |
| // Check for compression type | |
| if (head->compression != 1) { | |
| free(compBuffer); | |
| throw FLANNException("Compression type not supported"); | |
| } | |
| // Allocate a decompressed buffer | |
| ptr_ = buffer_ = (char *)malloc(uncompressedSz+headSz); | |
| if (buffer_ == NULL) { | |
| free(compBuffer); | |
| throw FLANNException("Error (re)allocating decompression buffer"); | |
| } | |
| // Extract body | |
| size_t usedSz = LZ4_decompress_safe(compBuffer+headSz, | |
| buffer_+headSz, | |
| compressedSz, | |
| uncompressedSz); | |
| // Check if the decompression was the expected size. | |
| if (usedSz != uncompressedSz) { | |
| free(compBuffer); | |
| throw FLANNException("Unexpected decompression size"); | |
| } | |
| // Copy header data | |
| memcpy(buffer_, compBuffer, headSz); | |
| free(compBuffer); | |
| // Put the file pointer at the end of the data we've read | |
| if (compressedSz+headSz+pos != fileSize) | |
| fseek(stream, compressedSz+headSz+pos, SEEK_SET); | |
| block_sz_ = uncompressedSz+headSz; | |
| } | |
| void initBlock(FILE *stream) | |
| { | |
| size_t pos = ftell(stream); | |
| buffer_ = NULL; | |
| buffer_blocks_ = NULL; | |
| compressed_buffer_ = NULL; | |
| size_t headSz = sizeof(IndexHeaderStruct); | |
| // Read the file header to a buffer | |
| IndexHeaderStruct *head = (IndexHeaderStruct *)malloc(headSz); | |
| if (head == NULL) { | |
| throw FLANNException("Error allocating header buffer space"); | |
| } | |
| if (fread(head, headSz, 1, stream) != 1) { | |
| free(head); | |
| throw FLANNException("Invalid index file, cannot read from disk (header)"); | |
| } | |
| // Backward compatability | |
| if (head->signature[13] == '1' && head->signature[15] == '0') { | |
| free(head); | |
| fseek(stream, pos, SEEK_SET); | |
| return decompressAndLoadV10(stream); | |
| } | |
| // Alloc the space for both buffer blocks (each block | |
| // references the previous) | |
| buffer_ = buffer_blocks_ = (char *)malloc(BLOCK_BYTES*2); | |
| compressed_buffer_ = (char *)malloc(LZ4_COMPRESSBOUND(BLOCK_BYTES)); | |
| if (buffer_ == NULL || compressed_buffer_ == NULL) { | |
| free(head); | |
| throw FLANNException("Error allocating compression buffer"); | |
| } | |
| // Init the LZ4 stream | |
| lz4StreamDecode = &lz4StreamDecode_body; | |
| LZ4_setStreamDecode(lz4StreamDecode, NULL, 0); | |
| // Read first block | |
| memcpy(buffer_, head, headSz); | |
| loadBlock(buffer_+headSz, head->first_block_size, stream); | |
| block_sz_ += headSz; | |
| ptr_ = buffer_; | |
| free(head); | |
| } | |
| void loadBlock(char* buffer_, size_t compSz, FILE* stream) | |
| { | |
| if(compSz >= LZ4_COMPRESSBOUND(BLOCK_BYTES)) { | |
| throw FLANNException("Requested block size too large"); | |
| } | |
| // Read the block into the compressed buffer | |
| if (fread(compressed_buffer_, compSz, 1, stream) != 1) { | |
| throw FLANNException("Invalid index file, cannot read from disk (block)"); | |
| } | |
| // Decompress into the regular buffer | |
| const int decBytes = LZ4_decompress_safe_continue( | |
| lz4StreamDecode, compressed_buffer_, buffer_, compSz, BLOCK_BYTES); | |
| if(decBytes <= 0) { | |
| throw FLANNException("Invalid index file, cannot decompress block"); | |
| } | |
| block_sz_ = decBytes; | |
| } | |
| void preparePtr(size_t size) | |
| { | |
| // Return if the new size is less than (or eq) the size of a block | |
| if (ptr_+size <= buffer_+block_sz_) | |
| return; | |
| // Switch the buffer to the *other* block | |
| if (buffer_ == buffer_blocks_) | |
| buffer_ = &buffer_blocks_[BLOCK_BYTES]; | |
| else | |
| buffer_ = buffer_blocks_; | |
| // Find the size of the next block | |
| size_t cmpSz = 0; | |
| size_t readCnt = fread(&cmpSz, sizeof(cmpSz), 1, stream_); | |
| if(cmpSz <= 0 || readCnt != 1) { | |
| throw FLANNException("Requested to read next block past end of file"); | |
| } | |
| // Load block & init ptr | |
| loadBlock(buffer_, cmpSz, stream_); | |
| ptr_ = buffer_; | |
| } | |
| void endBlock() | |
| { | |
| // If not v1.0 format hack... | |
| if (buffer_blocks_ != NULL) { | |
| // Read the last '0' in the file | |
| size_t zero = -1; | |
| if (fread(&zero, sizeof(zero), 1, stream_) != 1) { | |
| throw FLANNException("Invalid index file, cannot read from disk (end)"); | |
| } | |
| if (zero != 0) { | |
| throw FLANNException("Invalid index file, last block not zero length"); | |
| } | |
| } | |
| // Free resources | |
| if (buffer_blocks_ != NULL) { | |
| free(buffer_blocks_); | |
| buffer_blocks_ = NULL; | |
| } | |
| if (compressed_buffer_ != NULL) { | |
| free(compressed_buffer_); | |
| compressed_buffer_ = NULL; | |
| } | |
| ptr_ = NULL; | |
| } | |
| public: | |
| LoadArchive(const char* filename) | |
| { | |
| // Open the file | |
| stream_ = fopen(filename, "rb"); | |
| own_stream_ = true; | |
| initBlock(stream_); | |
| } | |
| LoadArchive(FILE* stream) | |
| { | |
| stream_ = stream; | |
| own_stream_ = false; | |
| initBlock(stream); | |
| } | |
| ~LoadArchive() | |
| { | |
| endBlock(); | |
| if (own_stream_) { | |
| fclose(stream_); | |
| } | |
| } | |
| template<typename T> | |
| void load(T& val) | |
| { | |
| preparePtr(sizeof(val)); | |
| memcpy(&val, ptr_, sizeof(val)); | |
| ptr_ += sizeof(val); | |
| } | |
| template<typename T> | |
| void load(T*& val) | |
| { | |
| // don't load pointers | |
| //fread(&val, sizeof(val), 1, handle_); | |
| } | |
| template<typename T> | |
| void load_binary(T* ptr, size_t size) | |
| { | |
| while (size > BLOCK_BYTES) { | |
| // Load next block | |
| preparePtr(BLOCK_BYTES); | |
| // Load large chunk | |
| memcpy(ptr, ptr_, BLOCK_BYTES); | |
| ptr_ += BLOCK_BYTES; | |
| ptr = ((char *)ptr) + BLOCK_BYTES; | |
| size -= BLOCK_BYTES; | |
| } | |
| // Load next block if needed | |
| preparePtr(size); | |
| // Load the data | |
| memcpy(ptr, ptr_, size); | |
| ptr_ += size; | |
| } | |
| }; | |
| } // namespace serialization | |
| } // namespace flann | |