From ccfaaefde499e82b97e0baf69033c79884756e82 Mon Sep 17 00:00:00 2001 From: David Wagner Date: Wed, 7 Sep 2016 17:14:44 +0200 Subject: [PATCH] Add binary and block serialization features Using the new `Binary` context mapping, parameters can now be written in binary format (in-memory serialization). The `File` instanciation mapping can now be asigned to blocks of parameters (but only in combination with the `Binary` context mapping, i.e. blocks can only be serialized in binary format). Signed-off-by: David Wagner --- FSMappingKeys.h | 1 + FSSubsystem.cpp | 1 + FSSubsystemObject.cpp | 73 ++++++++++++++++++++++++++++++------------- FSSubsystemObject.h | 2 ++ README.md | 14 +++++++++ 5 files changed, 69 insertions(+), 22 deletions(-) diff --git a/FSMappingKeys.h b/FSMappingKeys.h index 4245f89..1cd3211 100644 --- a/FSMappingKeys.h +++ b/FSMappingKeys.h @@ -33,6 +33,7 @@ // Mapping item types enum FSItemType { EFSDirectory, + EFSBinary, EFSAmend1, EFSAmend2, EFSAmend3, diff --git a/FSSubsystem.cpp b/FSSubsystem.cpp index b292374..6406cc7 100644 --- a/FSSubsystem.cpp +++ b/FSSubsystem.cpp @@ -41,6 +41,7 @@ CFSSubsystem::CFSSubsystem(const std::string& strName, core::log::Logger& logger { // Provide mapping keys to upper layer addContextMappingKey("Directory"); + addContextMappingKey("Binary"); addContextMappingKey("Amend1"); addContextMappingKey("Amend2"); addContextMappingKey("Amend3"); diff --git a/FSSubsystemObject.cpp b/FSSubsystemObject.cpp index f1365bc..5019248 100644 --- a/FSSubsystemObject.cpp +++ b/FSSubsystemObject.cpp @@ -61,15 +61,15 @@ CFSSubsystemObject::CFSSubsystemObject(const string& mappingValue, EFSAmend1, (EFSAmendEnd - EFSAmend1 + 1), context), - _wrongElementTypeErrorOccured(false), _stringFormat(false) + _wrongElementTypeErrorOccured(false), _stringFormat(false), _isBinary(context.iSet(EFSBinary)) { - // Get actual element type - const CParameterType* parameterType - = static_cast(instanceConfigurableElement->getTypeElement()); - // Retrieve sizes - _scalarSize = parameterType->getSize(); - _arraySize = instanceConfigurableElement->getFootPrint() / _scalarSize; + if (instanceConfigurableElement->isScalar()) { + _arraySize = 1; + } else { + _arraySize = instanceConfigurableElement->getArrayLength(); + } + _scalarSize = instanceConfigurableElement->getFootPrint() / _arraySize; // Amend _directoryPath = context.getItem(EFSDirectory) + "/"; @@ -82,6 +82,15 @@ CFSSubsystemObject::CFSSubsystemObject(const string& mappingValue, case CInstanceConfigurableElement::EStringParameter: _stringFormat = true; break; + case CInstanceConfigurableElement::EBitParameterBlock: + // fallthrough + case CInstanceConfigurableElement::EParameterBlock: + // fallthrough + case CInstanceConfigurableElement::EComponent: + if (not _isBinary) { + _wrongElementTypeErrorOccured = true; + } + break; default: _wrongElementTypeErrorOccured = true; break; @@ -93,7 +102,13 @@ bool CFSSubsystemObject::accessHW(bool receive, string& error) // Check parameter type is ok (deferred error, no exceptions available :-() if (_wrongElementTypeErrorOccured) { - error = "Only Parameter and StringParameter types are supported"; + if (_isBinary) { + error = "Only numerical Parameters, StringParameter, BitParameterBlock, ParameterBlocks" + " and Components are supported in binary mode."; + } else { + error = "Only Parameter and StringParameter types are supported in string mode (blocks" + " are not)."; + } return false; } @@ -147,8 +162,7 @@ bool CFSSubsystemObject::receiveFromHW(string& error) bool CFSSubsystemObject::sendToFile(int fileDesc, string& error) { uint32_t index; - int nbBytes; - string formatedContent; + ssize_t expectedWriteSize, actualWriteSize; void* blackboardContent = alloca(_scalarSize); string filePath = _directoryPath + getFormattedMappingValue(); @@ -157,18 +171,23 @@ bool CFSSubsystemObject::sendToFile(int fileDesc, string& error) // Read Value in BlackBoard blackboardRead(blackboardContent, _scalarSize); - formatedContent = toString(blackboardContent, _scalarSize); - // WARNING: Current C++ STL implementation of fstream operator '<<' cannot // write a string at once: it instead writes the first character and // then the remainining part of the string. // To support sysfs, we need to be able to write the string at once, // thus we use 'write' API. + if (_isBinary) { + expectedWriteSize = _scalarSize; + actualWriteSize = write(fileDesc, blackboardContent, _scalarSize); + } else { + string formatedContent = toString(blackboardContent, _scalarSize); + expectedWriteSize = formatedContent.size(); + + // Try to write the entire string + actualWriteSize = write(fileDesc, (const void *)formatedContent.c_str(), formatedContent.size()); + } - // Try to write the entire string - nbBytes = write(fileDesc, (const void *)formatedContent.c_str(), formatedContent.size()); - - if (nbBytes == -1) { + if (actualWriteSize == -1) { // Error when writing stringstream errorStream; errorStream << "Unable to write element #" << index << "over a total of " @@ -176,7 +195,7 @@ bool CFSSubsystemObject::sendToFile(int fileDesc, string& error) << " with error " << errno; error = errorStream.str(); return false; - } else if (nbBytes != (int)formatedContent.size()) { + } else if (actualWriteSize != expectedWriteSize) { // Did not write all characters at once stringstream errorStream; errorStream << "Unable to write element #" << index << "over a total of " @@ -192,8 +211,7 @@ bool CFSSubsystemObject::sendToFile(int fileDesc, string& error) bool CFSSubsystemObject::receiveFromFile(ifstream& inputFile, string& error) { uint32_t index; - char formatedContent[STR_FORMAT_LENGTH]; - void* blackboardContent = alloca(_scalarSize); + char blackboardContent[_scalarSize]; string filePath = _directoryPath + getFormattedMappingValue(); for (index = 0 ; index < _arraySize ; index++) { @@ -208,9 +226,20 @@ bool CFSSubsystemObject::receiveFromFile(ifstream& inputFile, string& error) return false; } - inputFile.getline(formatedContent, STR_FORMAT_LENGTH); - - fromString(formatedContent, blackboardContent, _scalarSize); + if (_isBinary) { + auto read = inputFile.readsome(blackboardContent, _scalarSize); + if (read != _scalarSize) { + stringstream errorStream; + errorStream << "Failed to read " << _scalarSize << " bytes from " << filePath; + error = errorStream.str(); + return false; + } + } else { + char formatedContent[STR_FORMAT_LENGTH]; + inputFile.getline(formatedContent, STR_FORMAT_LENGTH); + + fromString(formatedContent, blackboardContent, _scalarSize); + } // Write Value in Blackboard blackboardWrite(blackboardContent, _scalarSize); diff --git a/FSSubsystemObject.h b/FSSubsystemObject.h index f83c806..05e6738 100644 --- a/FSSubsystemObject.h +++ b/FSSubsystemObject.h @@ -135,4 +135,6 @@ class CFSSubsystemObject : public CFormattedSubsystemObject bool _wrongElementTypeErrorOccured; // Format for reading bool _stringFormat; + // Is the object to be written in binary format? + bool _isBinary; }; diff --git a/README.md b/README.md index f94a59f..7e60d49 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,20 @@ This is a file system plugin for the [parameter-framework](https://github.com/01org/parameter-framework) handling file system operations such as `read()` and `write()`. +By default, the plugin reads/writes individual parameters (numerical and +strings) as strings (one parameter per file or one array per file). This can +be overriden using the `Binary` mapping key; when added to a parameter or a +block (ParameterBlock or Component), the plugin reads/writes them in binary +(in-memory representation). e.g.: + +```xml + + + + + ... + +``` ## Compiling