Message ID | 20220604185939.29163-4-laurent.pinchart@ideasonboard.com |
---|---|
State | RFC |
Headers | show |
Series |
|
Related | show |
Hi Laurent, On Sat, Jun 04, 2022 at 09:59:28PM +0300, Laurent Pinchart via libcamera-devel wrote: > THe FILE object isn't very user-friendly as it requires manual close. > Replace it with File to provide RAII-style resource management in the > YamlParser API. > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Paul Elder <paul.elder@ideasonboard.com> > --- > include/libcamera/internal/yaml_parser.h | 4 +-- > src/android/camera_hal_config.cpp | 16 +++++----- > src/libcamera/yaml_parser.cpp | 39 +++++++++++++++++------- > test/yaml-parser.cpp | 18 +++++------ > 4 files changed, 47 insertions(+), 30 deletions(-) > > diff --git a/include/libcamera/internal/yaml_parser.h b/include/libcamera/internal/yaml_parser.h > index b4f852b1ce54..be5f0914703f 100644 > --- a/include/libcamera/internal/yaml_parser.h > +++ b/include/libcamera/internal/yaml_parser.h > @@ -7,7 +7,6 @@ > > #pragma once > > -#include <cstdio> > #include <map> > #include <string> > #include <vector> > @@ -18,6 +17,7 @@ > > namespace libcamera { > > +class File; > class YamlParserContext; > > class YamlObject > @@ -82,7 +82,7 @@ private: > class YamlParser final > { > public: > - static std::unique_ptr<YamlObject> parse(std::FILE *fh); > + static std::unique_ptr<YamlObject> parse(File &file); > }; > > } /* namespace libcamera */ > diff --git a/src/android/camera_hal_config.cpp b/src/android/camera_hal_config.cpp > index 8ba8738cc6b6..ac484b8df1bd 100644 > --- a/src/android/camera_hal_config.cpp > +++ b/src/android/camera_hal_config.cpp > @@ -10,6 +10,7 @@ > #include <stdlib.h> > #include <string> > > +#include <libcamera/base/file.h> > #include <libcamera/base/log.h> > > #include "libcamera/internal/yaml_parser.h" > @@ -27,7 +28,7 @@ class CameraHalConfig::Private : public Extensible::Private > public: > Private(); > > - int parseConfigFile(FILE *fh, std::map<std::string, CameraConfigData> *cameras); > + int parseConfigFile(File &file, std::map<std::string, CameraConfigData> *cameras); > > private: > int parseCameraConfigData(const std::string &cameraId, const YamlObject &); > @@ -41,7 +42,7 @@ CameraHalConfig::Private::Private() > { > } > > -int CameraHalConfig::Private::parseConfigFile(FILE *fh, > +int CameraHalConfig::Private::parseConfigFile(File &file, > std::map<std::string, CameraConfigData> *cameras) > { > /* > @@ -65,7 +66,7 @@ int CameraHalConfig::Private::parseConfigFile(FILE *fh, > > cameras_ = cameras; > > - std::unique_ptr<YamlObject> root = YamlParser::parse(fh); > + std::unique_ptr<YamlObject> root = YamlParser::parse(file); > if (!root) > return -EINVAL; > > @@ -169,9 +170,9 @@ int CameraHalConfig::parseConfigurationFile() > return -ENOENT; > } > > - FILE *fh = fopen(filePath.c_str(), "r"); > - if (!fh) { > - int ret = -errno; > + File file(filePath); > + if (!file.open(File::OpenModeFlag::ReadOnly)) { > + int ret = file.error(); > LOG(HALConfig, Error) << "Failed to open configuration file " > << filePath << ": " << strerror(-ret); > return ret; > @@ -179,8 +180,7 @@ int CameraHalConfig::parseConfigurationFile() > > exists_ = true; > > - int ret = _d()->parseConfigFile(fh, &cameras_); > - fclose(fh); > + int ret = _d()->parseConfigFile(file, &cameras_); > if (ret) > return -EINVAL; > > diff --git a/src/libcamera/yaml_parser.cpp b/src/libcamera/yaml_parser.cpp > index 5b872dbb0a2d..85f6694f5fde 100644 > --- a/src/libcamera/yaml_parser.cpp > +++ b/src/libcamera/yaml_parser.cpp > @@ -11,6 +11,7 @@ > #include <errno.h> > #include <functional> > > +#include <libcamera/base/file.h> > #include <libcamera/base/log.h> > > #include <yaml.h> > @@ -345,7 +346,7 @@ public: > YamlParserContext(); > ~YamlParserContext(); > > - int init(std::FILE *fh); > + int init(File &file); > int parseContent(YamlObject &yamlObject); > > private: > @@ -358,6 +359,9 @@ private: > }; > using EventPtr = std::unique_ptr<yaml_event_t, EventDeleter>; > > + static int yamlRead(void *data, unsigned char *buffer, size_t size, > + size_t *sizeRead); > + > EventPtr nextEvent(); > > void readValue(std::string &value, EventPtr event); > @@ -399,13 +403,13 @@ YamlParserContext::~YamlParserContext() > * \param[in] fh The YAML file to parse > * > * Prior to parsing the YAML content, the YamlParserContext must be initialized > - * with an opened FILE to create an internal parser. The FILE needs to stay > - * valid during the process. > + * with a file to create an internal parser. The file needs to stay valid until > + * parsing completes. > * > * \return 0 on success or a negative error code otherwise > * \retval -EINVAL The parser has failed to initialize > */ > -int YamlParserContext::init(std::FILE *fh) > +int YamlParserContext::init(File &file) > { > /* yaml_parser_initialize returns 1 when it succeededs */ > if (!yaml_parser_initialize(&parser_)) { > @@ -413,11 +417,25 @@ int YamlParserContext::init(std::FILE *fh) > return -EINVAL; > } > parserValid_ = true; > - yaml_parser_set_input_file(&parser_, fh); > + yaml_parser_set_input(&parser_, &YamlParserContext::yamlRead, &file); > > return 0; > } > > +int YamlParserContext::yamlRead(void *data, unsigned char *buffer, size_t size, > + size_t *sizeRead) > +{ > + File *file = static_cast<File *>(data); > + > + Span<unsigned char> buf{ buffer, size }; > + ssize_t ret = file->read(buf); > + if (ret < 0) > + return 0; > + > + *sizeRead = ret; > + return 1; > +} > + > /** > * \fn YamlParserContext::nextEvent() > * \brief Get the next event > @@ -655,21 +673,20 @@ int YamlParserContext::parseNextYamlObject(YamlObject &yamlObject, EventPtr even > */ > > /** > - * \fn YamlParser::parse() > * \brief Parse a YAML file as a YamlObject > - * \param[in] fh The YAML file to parse > + * \param[in] file The YAML file to parse > * > - * The YamlParser::parse() function takes an open FILE, parses its contents, and > + * The YamlParser::parse() function takes a file, parses its contents, and > * returns a pointer to a YamlObject corresponding to the root node of the YAML > - * document. The caller is responsible for closing the file. > + * document. > * > * \return Pointer to result YamlObject on success or nullptr otherwise > */ > -std::unique_ptr<YamlObject> YamlParser::parse(std::FILE *fh) > +std::unique_ptr<YamlObject> YamlParser::parse(File &file) > { > YamlParserContext context; > > - if (context.init(fh)) > + if (context.init(file)) > return nullptr; > > std::unique_ptr<YamlObject> root(new YamlObject()); > diff --git a/test/yaml-parser.cpp b/test/yaml-parser.cpp > index c5b4ddbb19e5..e75f8fe8f642 100644 > --- a/test/yaml-parser.cpp > +++ b/test/yaml-parser.cpp > @@ -9,6 +9,8 @@ > #include <string> > #include <unistd.h> > > +#include <libcamera/base/file.h> > + > #include "libcamera/internal/yaml_parser.h" > > #include "test.h" > @@ -69,29 +71,27 @@ protected: > int run() > { > /* Test invalid YAML file */ > - FILE *fh = fopen(invalidYamlFile_.c_str(), "r"); > - if (!fh) { > + File file{ invalidYamlFile_ }; > + if (!file.open(File::OpenModeFlag::ReadOnly)) { > cerr << "Fail to open invalid YAML file" << std::endl; > return TestFail; > } > > - std::unique_ptr<YamlObject> root = YamlParser::parse(fh); > - fclose(fh); > - > + std::unique_ptr<YamlObject> root = YamlParser::parse(file); > if (root) { > cerr << "Invalid YAML file parse successfully" << std::endl; > return TestFail; > } > > /* Test YAML file */ > - fh = fopen(testYamlFile_.c_str(), "r"); > - if (!fh) { > + file.close(); > + file.setFileName(testYamlFile_); > + if (!file.open(File::OpenModeFlag::ReadOnly)) { > cerr << "Fail to open test YAML file" << std::endl; > return TestFail; > } > > - root = YamlParser::parse(fh); > - fclose(fh); > + root = YamlParser::parse(file); > > if (!root) { > cerr << "Fail to parse test YAML file: " << std::endl; > -- > Regards, > > Laurent Pinchart >
diff --git a/include/libcamera/internal/yaml_parser.h b/include/libcamera/internal/yaml_parser.h index b4f852b1ce54..be5f0914703f 100644 --- a/include/libcamera/internal/yaml_parser.h +++ b/include/libcamera/internal/yaml_parser.h @@ -7,7 +7,6 @@ #pragma once -#include <cstdio> #include <map> #include <string> #include <vector> @@ -18,6 +17,7 @@ namespace libcamera { +class File; class YamlParserContext; class YamlObject @@ -82,7 +82,7 @@ private: class YamlParser final { public: - static std::unique_ptr<YamlObject> parse(std::FILE *fh); + static std::unique_ptr<YamlObject> parse(File &file); }; } /* namespace libcamera */ diff --git a/src/android/camera_hal_config.cpp b/src/android/camera_hal_config.cpp index 8ba8738cc6b6..ac484b8df1bd 100644 --- a/src/android/camera_hal_config.cpp +++ b/src/android/camera_hal_config.cpp @@ -10,6 +10,7 @@ #include <stdlib.h> #include <string> +#include <libcamera/base/file.h> #include <libcamera/base/log.h> #include "libcamera/internal/yaml_parser.h" @@ -27,7 +28,7 @@ class CameraHalConfig::Private : public Extensible::Private public: Private(); - int parseConfigFile(FILE *fh, std::map<std::string, CameraConfigData> *cameras); + int parseConfigFile(File &file, std::map<std::string, CameraConfigData> *cameras); private: int parseCameraConfigData(const std::string &cameraId, const YamlObject &); @@ -41,7 +42,7 @@ CameraHalConfig::Private::Private() { } -int CameraHalConfig::Private::parseConfigFile(FILE *fh, +int CameraHalConfig::Private::parseConfigFile(File &file, std::map<std::string, CameraConfigData> *cameras) { /* @@ -65,7 +66,7 @@ int CameraHalConfig::Private::parseConfigFile(FILE *fh, cameras_ = cameras; - std::unique_ptr<YamlObject> root = YamlParser::parse(fh); + std::unique_ptr<YamlObject> root = YamlParser::parse(file); if (!root) return -EINVAL; @@ -169,9 +170,9 @@ int CameraHalConfig::parseConfigurationFile() return -ENOENT; } - FILE *fh = fopen(filePath.c_str(), "r"); - if (!fh) { - int ret = -errno; + File file(filePath); + if (!file.open(File::OpenModeFlag::ReadOnly)) { + int ret = file.error(); LOG(HALConfig, Error) << "Failed to open configuration file " << filePath << ": " << strerror(-ret); return ret; @@ -179,8 +180,7 @@ int CameraHalConfig::parseConfigurationFile() exists_ = true; - int ret = _d()->parseConfigFile(fh, &cameras_); - fclose(fh); + int ret = _d()->parseConfigFile(file, &cameras_); if (ret) return -EINVAL; diff --git a/src/libcamera/yaml_parser.cpp b/src/libcamera/yaml_parser.cpp index 5b872dbb0a2d..85f6694f5fde 100644 --- a/src/libcamera/yaml_parser.cpp +++ b/src/libcamera/yaml_parser.cpp @@ -11,6 +11,7 @@ #include <errno.h> #include <functional> +#include <libcamera/base/file.h> #include <libcamera/base/log.h> #include <yaml.h> @@ -345,7 +346,7 @@ public: YamlParserContext(); ~YamlParserContext(); - int init(std::FILE *fh); + int init(File &file); int parseContent(YamlObject &yamlObject); private: @@ -358,6 +359,9 @@ private: }; using EventPtr = std::unique_ptr<yaml_event_t, EventDeleter>; + static int yamlRead(void *data, unsigned char *buffer, size_t size, + size_t *sizeRead); + EventPtr nextEvent(); void readValue(std::string &value, EventPtr event); @@ -399,13 +403,13 @@ YamlParserContext::~YamlParserContext() * \param[in] fh The YAML file to parse * * Prior to parsing the YAML content, the YamlParserContext must be initialized - * with an opened FILE to create an internal parser. The FILE needs to stay - * valid during the process. + * with a file to create an internal parser. The file needs to stay valid until + * parsing completes. * * \return 0 on success or a negative error code otherwise * \retval -EINVAL The parser has failed to initialize */ -int YamlParserContext::init(std::FILE *fh) +int YamlParserContext::init(File &file) { /* yaml_parser_initialize returns 1 when it succeededs */ if (!yaml_parser_initialize(&parser_)) { @@ -413,11 +417,25 @@ int YamlParserContext::init(std::FILE *fh) return -EINVAL; } parserValid_ = true; - yaml_parser_set_input_file(&parser_, fh); + yaml_parser_set_input(&parser_, &YamlParserContext::yamlRead, &file); return 0; } +int YamlParserContext::yamlRead(void *data, unsigned char *buffer, size_t size, + size_t *sizeRead) +{ + File *file = static_cast<File *>(data); + + Span<unsigned char> buf{ buffer, size }; + ssize_t ret = file->read(buf); + if (ret < 0) + return 0; + + *sizeRead = ret; + return 1; +} + /** * \fn YamlParserContext::nextEvent() * \brief Get the next event @@ -655,21 +673,20 @@ int YamlParserContext::parseNextYamlObject(YamlObject &yamlObject, EventPtr even */ /** - * \fn YamlParser::parse() * \brief Parse a YAML file as a YamlObject - * \param[in] fh The YAML file to parse + * \param[in] file The YAML file to parse * - * The YamlParser::parse() function takes an open FILE, parses its contents, and + * The YamlParser::parse() function takes a file, parses its contents, and * returns a pointer to a YamlObject corresponding to the root node of the YAML - * document. The caller is responsible for closing the file. + * document. * * \return Pointer to result YamlObject on success or nullptr otherwise */ -std::unique_ptr<YamlObject> YamlParser::parse(std::FILE *fh) +std::unique_ptr<YamlObject> YamlParser::parse(File &file) { YamlParserContext context; - if (context.init(fh)) + if (context.init(file)) return nullptr; std::unique_ptr<YamlObject> root(new YamlObject()); diff --git a/test/yaml-parser.cpp b/test/yaml-parser.cpp index c5b4ddbb19e5..e75f8fe8f642 100644 --- a/test/yaml-parser.cpp +++ b/test/yaml-parser.cpp @@ -9,6 +9,8 @@ #include <string> #include <unistd.h> +#include <libcamera/base/file.h> + #include "libcamera/internal/yaml_parser.h" #include "test.h" @@ -69,29 +71,27 @@ protected: int run() { /* Test invalid YAML file */ - FILE *fh = fopen(invalidYamlFile_.c_str(), "r"); - if (!fh) { + File file{ invalidYamlFile_ }; + if (!file.open(File::OpenModeFlag::ReadOnly)) { cerr << "Fail to open invalid YAML file" << std::endl; return TestFail; } - std::unique_ptr<YamlObject> root = YamlParser::parse(fh); - fclose(fh); - + std::unique_ptr<YamlObject> root = YamlParser::parse(file); if (root) { cerr << "Invalid YAML file parse successfully" << std::endl; return TestFail; } /* Test YAML file */ - fh = fopen(testYamlFile_.c_str(), "r"); - if (!fh) { + file.close(); + file.setFileName(testYamlFile_); + if (!file.open(File::OpenModeFlag::ReadOnly)) { cerr << "Fail to open test YAML file" << std::endl; return TestFail; } - root = YamlParser::parse(fh); - fclose(fh); + root = YamlParser::parse(file); if (!root) { cerr << "Fail to parse test YAML file: " << std::endl;
THe FILE object isn't very user-friendly as it requires manual close. Replace it with File to provide RAII-style resource management in the YamlParser API. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> --- include/libcamera/internal/yaml_parser.h | 4 +-- src/android/camera_hal_config.cpp | 16 +++++----- src/libcamera/yaml_parser.cpp | 39 +++++++++++++++++------- test/yaml-parser.cpp | 18 +++++------ 4 files changed, 47 insertions(+), 30 deletions(-)