From 96933edcedc39914d3bf3701998f9c188ebceab3 Mon Sep 17 00:00:00 2001 From: diegohce Date: Sun, 1 Sep 2024 06:03:58 -0300 Subject: [PATCH] Filestorage roadmap (#1208) FileStorage: added FileStorage features --- persistence.h | 77 ++++++++++++++ persistence_filenode.cpp | 113 ++++++++++++++++++++ persistence_filenode.go | 84 +++++++++++++++ persistence_filestorage.cpp | 113 ++++++++++++++++++++ persistence_filestorage.go | 202 ++++++++++++++++++++++++++++++++++++ persistence_test.go | 57 ++++++++++ 6 files changed, 646 insertions(+) create mode 100644 persistence.h create mode 100644 persistence_filenode.cpp create mode 100644 persistence_filenode.go create mode 100644 persistence_filestorage.cpp create mode 100644 persistence_filestorage.go create mode 100644 persistence_test.go diff --git a/persistence.h b/persistence.h new file mode 100644 index 00000000..b54fcbd3 --- /dev/null +++ b/persistence.h @@ -0,0 +1,77 @@ +#ifndef _OPENCV3_OBJDETECT_H_ +#define _OPENCV3_OBJDETECT_H_ + +#include + +#ifdef __cplusplus +#include +extern "C" { +#endif + +#include "core.h" + +#ifdef __cplusplus +typedef cv::FileStorage* FileStorage; +typedef cv::FileNode* FileNode; +#else +typedef void* FileStorage; +typedef void* FileNode; +#endif + +// FileStorage +FileStorage FileStorage_Create(void); +FileStorage FileStorage_CreateWithParams(const char* filename, int flags, const char* encoding); +void FileStorage_Close(FileStorage fs); + +const char *FileStorage_ElName(FileStorage fs); +int FileStorage_State(FileStorage fs); + +void FileStorage_EndWriteStruct(FileStorage fs); +int FileStorage_GetFormat(FileStorage fs); +bool FileStorage_IsOpened(FileStorage fs); +bool FileStorage_Open(FileStorage fs, const char* filename, int flags, const char* encoding); +void FileStorage_Release(FileStorage fs); +const char* FileStorage_ReleaseAndGetString(FileStorage fs); +void FileStorage_StartWriteStruct(FileStorage fs, const char* name, int flags, const char* typeName); +void FileStorage_WriteMat(FileStorage fs, const char* name, Mat val); +void FileStorage_WriteString(FileStorage fs, const char* name, const char* val); +void FileStorage_WriteStringArray(FileStorage fs, const char* name, const char** val, size_t len); +void FileStorage_WriteDouble(FileStorage fs, const char* name, double val); +void FileStorage_WriteInt(FileStorage fs, const char* name, int val); +void FileStorage_WriteComment(FileStorage fs, const char* comment, bool append); +void FileStorage_WriteRaw(FileStorage fs, const char* fmt, const void* vec, size_t len); + +FileNode FileStorage_GetFirstTopLevelNode(FileStorage fs); +FileNode FileStorage_GetNode(FileStorage fs, const char* nodename); +FileNode FileStorage_Root(FileStorage fs, int streamidx); + +bool FileNode_Empty(FileNode fn); +bool FileNode_IsInt(FileNode fn); +bool FileNode_IsMap(FileNode fn); +bool FileNode_IsNamed(FileNode fn); +bool FileNode_IsNone(FileNode fn); +bool FileNode_IsReal(FileNode fn); +bool FileNode_IsSeq(FileNode fn); +bool FileNode_IsString(FileNode fn); +char** FileNode_Keys(FileNode fn); +size_t FileNode_KeysCount(FileNode fn); +void FileNode_KeysFree(char** keys, size_t len); +Mat FileNode_Mat(FileNode fn); +const char* FileNode_Name(FileNode fn); +float FileNode_Float(FileNode fn); +const char* FileNode_String(FileNode fn); +FileNode FileNode_Get(FileNode fn, int i); //FileNode operator[] (int i) const +FileNode FileNode_GetByName(FileNode fn, const char* nodename); //FileNode operator[] (const char *nodename) const +size_t FileNode_RawSize(FileNode fn); +void FileNode_ReadRaw(FileNode fn, const char* fmt, void *vec, size_t len); +void FileNode_SetValue(FileNode fn, int type, const void *value, int len); +size_t FileNode_Size(FileNode fn); +int FileNode_Type(FileNode fn); + +void FileNode_Close(FileNode fn); + +#ifdef __cplusplus +} +#endif + +#endif //_OPENCV3_OBJDETECT_H_ diff --git a/persistence_filenode.cpp b/persistence_filenode.cpp new file mode 100644 index 00000000..0364f65e --- /dev/null +++ b/persistence_filenode.cpp @@ -0,0 +1,113 @@ +#include +#include "persistence.h" + +bool FileNode_Empty(FileNode fn) { + return fn->empty(); +} + +bool FileNode_IsInt(FileNode fn){ + return fn->isInt(); +} + +bool FileNode_IsMap(FileNode fn){ + return fn->isMap(); +} + +bool FileNode_IsNamed(FileNode fn) { + return fn->isNamed(); +} + +bool FileNode_IsNone(FileNode fn){ + return fn->isNone(); +} + +bool FileNode_IsReal(FileNode fn){ + return fn->isReal(); +} + +bool FileNode_IsSeq(FileNode fn) { + return fn->isSeq(); +} + +bool FileNode_IsString(FileNode fn) { + return fn->isString(); +} + +char** FileNode_Keys(FileNode fn) { + + std::vector keys = fn->keys(); + + char** c_keys = new char*[keys.size()]; + + for (int i = 0; i < keys.size(); i++) { + char *c_key = new char[keys[i].length()+1]; + strcpy(c_key, keys[i].c_str()); + c_keys[i] = c_key; + } + + return c_keys; +} + +size_t FileNode_KeysCount(FileNode fn) { + return fn->keys().size(); +} + + +void FileNode_KeysFree(char** keys, size_t len) { + for(int i = 0; i < len; i++) { + delete keys[i]; + } + delete keys; +} + +Mat FileNode_Mat(FileNode fn) { + return new cv::Mat(fn->mat()); +} + +const char* FileNode_Name(FileNode fn) { + char* str = new char[fn->name().length()+1]; + strcpy(str, fn->name().c_str()); + return str; +} + +float FileNode_Float(FileNode fn) { + return (float)fn->real(); +} + +const char* FileNode_String(FileNode fn) { + char* str = new char[fn->string().length()+1]; + strcpy(str, fn->string().c_str()); + return str; +} + +FileNode FileNode_Get(FileNode fn, int i) { + return new cv::FileNode((*fn)[i]); +} + +FileNode FileNode_GetByName(FileNode fn, const char* nodename) { + return new cv::FileNode((*fn)[nodename]); +} + +size_t FileNode_RawSize(FileNode fn) { + return fn->rawSize(); +} + +void FileNode_ReadRaw(FileNode fn, const char* fmt, void *vec, size_t len) { + fn->readRaw(fmt, vec, len); +} + +void FileNode_SetValue(FileNode fn, int type, const void *value, int len) { + fn->setValue(type, value, len); +} + +size_t FileNode_Size(FileNode fn) { + return fn->size(); +} + +int FileNode_Type(FileNode fn) { + return fn->type(); +} + +void FileNode_Close(FileNode fn){ + delete fn; +} diff --git a/persistence_filenode.go b/persistence_filenode.go new file mode 100644 index 00000000..c907cd58 --- /dev/null +++ b/persistence_filenode.go @@ -0,0 +1,84 @@ +package gocv + +/* +#include +#include "persistence.h" +*/ +import "C" +import "unsafe" + +type FileNodeType int + +const ( + FileNodeTypeNone FileNodeType = 0 + FileNodeTypeInt FileNodeType = 1 + FileNodeTypeReal FileNodeType = 2 + FileNodeTypeFloat FileNodeType = FileNodeTypeReal + FileNodeTypeStr FileNodeType = 3 + FileNodeTypeString FileNodeType = FileNodeTypeStr + FileNodeTypeSeq FileNodeType = 4 + FileNodeTypeMap FileNodeType = 5 + FileNodeTypeTypeMask FileNodeType = 7 + FileNodeTypeFlow FileNodeType = 8 + FileNodeTypeUniform FileNodeType = 8 + FileNodeTypeEmpty FileNodeType = 16 + FileNodeTypeNamed FileNodeType = 32 +) + +// FileNode is a wrapper for the OpenCV FileNode class +// +// Ref: https://docs.opencv.org/4.x/de/dd9/classcv_1_1FileNode.html +type FileNode struct { + p C.FileNode +} + +func (fn *FileNode) Empty() bool { + return bool(C.FileNode_Empty(fn.p)) +} + +func (fn *FileNode) IsInt() bool { + return bool(C.FileNode_IsInt(fn.p)) +} + +func (fn *FileNode) IsMap() bool { + return bool(C.FileNode_IsMap(fn.p)) +} + +func (fn *FileNode) IsNamed() bool { + return bool(C.FileNode_IsNamed(fn.p)) +} + +func (fn *FileNode) IsNone() bool { + return bool(C.FileNode_IsNone(fn.p)) +} + +func (fn *FileNode) IsReal() bool { + return bool(C.FileNode_IsReal(fn.p)) +} + +func (fn *FileNode) IsSeq() bool { + return bool(C.FileNode_IsSeq(fn.p)) +} + +func (fn *FileNode) IsString() bool { + return bool(C.FileNode_IsString(fn.p)) +} + +func (fn *FileNode) Keys() []string { + + c_keys_count := C.FileNode_KeysCount(fn.p) + c_keys := C.FileNode_Keys(fn.p) + defer C.FileNode_KeysFree(c_keys, c_keys_count) + + keys := make([]string, int(c_keys_count)) + c_keys_slice := unsafe.Slice(c_keys, c_keys_count) + + for i := 0; i < int(c_keys_count); i++ { + keys[i] = C.GoString(c_keys_slice[i]) + } + return keys +} + +func (fn *FileNode) Close() { + C.FileNode_Close(fn.p) +} diff --git a/persistence_filestorage.cpp b/persistence_filestorage.cpp new file mode 100644 index 00000000..9675f617 --- /dev/null +++ b/persistence_filestorage.cpp @@ -0,0 +1,113 @@ +#include +#include "persistence.h" + + +FileStorage FileStorage_Create(void) { + return new cv::FileStorage(); +} + +FileStorage FileStorage_CreateWithParams(const char* filename, int flags, const char* encoding) { + return new cv::FileStorage(filename, flags, encoding); +} + +const char *FileStorage_ElName(FileStorage fs) { + char* str = new char[fs->elname.length()+1]; + strcpy(str, fs->elname.c_str()); + return str; +} +int FileStorage_State(FileStorage fs) { + return fs->state; +} + +void FileStorage_Close(FileStorage fs) { + fs->release(); + delete fs; +} + +void FileStorage_EndWriteStruct(FileStorage fs) { + fs->endWriteStruct(); +} + +int FileStorage_GetFormat(FileStorage fs){ + return fs->getFormat(); +} + +bool FileStorage_IsOpened(FileStorage fs) { + return fs->isOpened(); +} + +bool FileStorage_Open(FileStorage fs, const char* filename, int flags, const char* encoding) { + return fs->open(filename, flags, encoding); +} + +void FileStorage_Release(FileStorage fs) { + fs->release(); + delete fs; +} + +const char* FileStorage_ReleaseAndGetString(FileStorage fs) { + cv::String s = fs->releaseAndGetString(); + + char* str = new char[s.length()+1]; + strcpy(str, s.c_str()); + return str; +} + +void FileStorage_StartWriteStruct(FileStorage fs, const char* name, int flags, const char* typeName){ + fs->startWriteStruct(name, flags, typeName); +} + +void FileStorage_WriteMat(FileStorage fs, const char* name, Mat val){ + fs->write(name, *val); +} + +void FileStorage_WriteString(FileStorage fs, const char* name, const char* val) { + fs->write(name, val); +} + +void FileStorage_WriteStringArray(FileStorage fs, const char* name, const char** val, size_t len) { + std::vector vals; + + for(int i = 0; i < len; i++) { + vals.push_back(val[i]); + } + + fs->write(name, vals); +} + +void FileStorage_WriteDouble(FileStorage fs, const char* name, double val){ + fs->write(name, val); +} + +void FileStorage_WriteInt(FileStorage fs, const char* name, int val){ + fs->write(name, val); +} + +void FileStorage_WriteComment(FileStorage fs, const char* comment, bool append){ + fs->writeComment(comment, append); +} +void FileStorage_WriteRaw(FileStorage fs, const char* fmt, const void* vec, size_t len){ + fs->writeRaw(fmt, vec, len); +} + +FileNode FileStorage_GetFirstTopLevelNode(FileStorage fs) { + cv::FileNode node = fs->getFirstTopLevelNode(); + + FileNode fn = new cv::FileNode(node); + return fn; +} + +FileNode FileStorage_GetNode(FileStorage fs, const char* nodename) { + + cv::FileNode node = (*fs)[nodename]; + + FileNode fn = new cv::FileNode(node); + return fn; +} + +FileNode FileStorage_Root(FileStorage fs, int streamidx) { + cv::FileNode node = fs->root(streamidx); + + FileNode fn = new cv::FileNode(node); + return fn; +} \ No newline at end of file diff --git a/persistence_filestorage.go b/persistence_filestorage.go new file mode 100644 index 00000000..c0d08aee --- /dev/null +++ b/persistence_filestorage.go @@ -0,0 +1,202 @@ +package gocv + +/* +#include +#include +#include "persistence.h" +*/ +import "C" +import "unsafe" + +type FileStorageMode int + +const ( + FileStorageModeRead FileStorageMode = 0 + FileStorageModeWrite FileStorageMode = 1 + FileStorageModeAppend FileStorageMode = 2 + FileStorageModeMemory FileStorageMode = 4 + FileStorageModeFormatMask FileStorageMode = (7 << 3) + FileStorageModeFormatAuto FileStorageMode = 0 + FileStorageModeFormatXml FileStorageMode = (1 << 3) + FileStorageModeFormatYaml FileStorageMode = (2 << 3) + FileStorageModeFormatJson FileStorageMode = (3 << 3) + FileStorageModeBase64 FileStorageMode = 64 + FileStorageModeWriteBase64 FileStorageMode = FileStorageModeBase64 | FileStorageModeWrite +) + +type FileStorageState int + +const ( + FileStorageStateUndefined FileStorageState = 0 + FileStorageStateValueExpected FileStorageState = 1 + FileStorageStateNameExpected FileStorageState = 2 + FileStorageStateInsideMap FileStorageState = 4 +) + +// FileStorage is a wrapper for the OpenCV FileStorage class +// +// Ref: https://docs.opencv.org/4.x/da/d56/classcv_1_1FileStorage.html +type FileStorage struct { + p C.FileStorage +} + +func NewFileStorage() *FileStorage { + return &FileStorage{p: C.FileStorage_Create()} +} + +func NewFileStorageWithParams(filename string, flags FileStorageMode, encoding string) *FileStorage { + c_filename := C.CString(filename) + c_encoding := C.CString(encoding) + defer C.free(unsafe.Pointer(c_filename)) + defer C.free(unsafe.Pointer(c_encoding)) + + return &FileStorage{p: C.FileStorage_CreateWithParams(c_filename, C.int(flags), c_encoding)} +} + +func (fs *FileStorage) Close() { + fs.Release() +} + +func (fs *FileStorage) Release() { + C.FileStorage_Release(fs.p) +} + +func (fs *FileStorage) ElName() string { + c_str := C.FileStorage_ElName(fs.p) + defer C.free(unsafe.Pointer(c_str)) + + str := C.GoString(c_str) + return str +} + +func (fs *FileStorage) State() FileStorageState { + state := C.FileStorage_State(fs.p) + return FileStorageState(int(state)) +} + +func (fs *FileStorage) EndWriteStruct() { + C.FileStorage_EndWriteStruct(fs.p) + +} + +func (fs *FileStorage) GetFormat() FileStorageMode { + fmt := C.FileStorage_GetFormat(fs.p) + return FileStorageMode(int(fmt)) +} + +func (fs *FileStorage) IsOpened() bool { + b := C.FileStorage_IsOpened(fs.p) + return bool(b) +} + +func (fs *FileStorage) Open(filename string, flags FileStorageMode, encoding string) bool { + c_filename := C.CString(filename) + c_encoding := C.CString(encoding) + defer C.free(unsafe.Pointer(c_filename)) + defer C.free(unsafe.Pointer(c_encoding)) + + b := C.FileStorage_Open(fs.p, c_filename, C.int(flags), c_encoding) + return bool(b) +} + +func (fs *FileStorage) ReleaseAndGetString() string { + c_str := C.FileStorage_ReleaseAndGetString(fs.p) + defer C.free(unsafe.Pointer(c_str)) + + str := C.GoString(c_str) + return str +} + +func (fs *FileStorage) StartWriteStruct(name string, flags FileNodeType, typeName string) { + c_name := C.CString(name) + c_typeName := C.CString(typeName) + defer C.free(unsafe.Pointer(c_name)) + defer C.free(unsafe.Pointer(c_typeName)) + + C.FileStorage_StartWriteStruct(fs.p, c_name, C.int(flags), c_typeName) +} + +func (fs *FileStorage) WriteMat(name string, mat Mat) { + c_name := C.CString(name) + defer C.free(unsafe.Pointer(c_name)) + + C.FileStorage_WriteMat(fs.p, c_name, mat.p) +} + +func (fs *FileStorage) WriteString(name string, val string) { + c_name := C.CString(name) + c_val := C.CString(val) + defer C.free(unsafe.Pointer(c_name)) + defer C.free(unsafe.Pointer(c_val)) + + C.FileStorage_WriteString(fs.p, c_name, c_val) +} + +func (fs *FileStorage) WriteStringArray(name string, val []string) { + c_name := C.CString(name) + defer C.free(unsafe.Pointer(c_name)) + + c_val := make([]*C.char, 0, len(val)) + + for _, v := range val { + c_val = append(c_val, C.CString(v)) + } + defer func() { + for _, p := range c_val { + C.free(unsafe.Pointer(p)) + } + }() + C.FileStorage_WriteStringArray(fs.p, c_name, &c_val[0], C.size_t(len(val))) +} + +func (fs *FileStorage) WriteDouble(name string, val float32) { + c_name := C.CString(name) + defer C.free(unsafe.Pointer(c_name)) + + C.FileStorage_WriteDouble(fs.p, c_name, C.double(val)) +} + +func (fs *FileStorage) WriteInt(name string, val int) { + c_name := C.CString(name) + defer C.free(unsafe.Pointer(c_name)) + + C.FileStorage_WriteInt(fs.p, c_name, C.int(val)) +} + +func (fs *FileStorage) WriteComment(comment string, append bool) { + c_comment := C.CString(comment) + defer C.free(unsafe.Pointer(c_comment)) + + C.FileStorage_WriteComment(fs.p, c_comment, C.bool(append)) +} + +func (fs *FileStorage) WriteRaw(fmt string, vec []byte) { + c_fmt := C.CString(fmt) + defer C.free(unsafe.Pointer(c_fmt)) + + c_vec := C.CBytes(vec) + defer C.free(c_vec) + + C.FileStorage_WriteRaw(fs.p, c_fmt, c_vec, C.size_t(len(vec))) + +} + +func (fs *FileStorage) GetFirstTopLevelNode() *FileNode { + node_p := C.FileStorage_GetFirstTopLevelNode(fs.p) + return &FileNode{p: node_p} +} + +func (fs *FileStorage) GetNode(name string) *FileNode { + c_name := C.CString(name) + defer C.free(unsafe.Pointer(c_name)) + + node_p := C.FileStorage_GetNode(fs.p, c_name) + + return &FileNode{p: node_p} + +} + +func (fs *FileStorage) Root(streamIdx int) *FileNode { + node_p := C.FileStorage_Root(fs.p, C.int(streamIdx)) + return &FileNode{p: node_p} +} diff --git a/persistence_test.go b/persistence_test.go new file mode 100644 index 00000000..ad3898b1 --- /dev/null +++ b/persistence_test.go @@ -0,0 +1,57 @@ +package gocv + +import ( + "os" + "path/filepath" + "testing" +) + +func TestFileStorage(t *testing.T) { + + fileStorageTestFilename := filepath.Join(os.TempDir(), "filestorage.json") + fs := NewFileStorageWithParams(fileStorageTestFilename, FileStorageModeWrite|FileStorageModeFormatJson, "utf-8") + + fs.StartWriteStruct("gocv", FileNodeTypeMap, "person") + fs.ElName() + fs.State() + fs.GetFormat() + fs.IsOpened() + + m := NewMat() + defer m.Close() + fs.WriteMat("mat", m) + + fs.WriteString("string", "string value") + fs.WriteStringArray("stringArray", []string{"string", "array"}) + fs.WriteDouble("double", 3.1415927) + fs.WriteInt("int", 42) + fs.WriteComment("no comments", true) + + fs.EndWriteStruct() + + fs.StartWriteStruct("gocv2", FileNodeTypeSeq, "int") + fs.WriteRaw("u", []byte{0, 0}) + fs.EndWriteStruct() + + fs.GetNode("gocv") + fs.Root(0) + + fs.ReleaseAndGetString() + + fs = NewFileStorage() + fs.Open(fileStorageTestFilename, FileStorageModeRead|FileStorageModeFormatJson, "utf-8") + + fn := fs.GetFirstTopLevelNode() + defer fn.Close() + + fn.Empty() + fn.IsInt() + fn.IsMap() + fn.IsNamed() + fn.IsNone() + fn.IsReal() + fn.IsSeq() + fn.IsString() + fn.Keys() + fs.Release() +}