libcamera: utils: Add hex stream output helper

Add a utils::hex() function that simplifies writing hexadecimal values
to an ostream. The function handles the '0x' prefix, the field width and
the fill character automatically. Use it through the libcamera code
base, and add a test.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>
This commit is contained in:
Laurent Pinchart 2019-10-13 22:22:04 +03:00
parent ce739e616c
commit f391048a7b
11 changed files with 147 additions and 22 deletions

View file

@ -640,7 +640,7 @@ int CameraDevice::configureStreams(camera3_stream_configuration_t *stream_list)
<< ", direction: " << stream->stream_type
<< ", width: " << stream->width
<< ", height: " << stream->height
<< ", format: " << std::hex << stream->format;
<< ", format: " << utils::hex(stream->format);
}
/* Hardcode viewfinder role, collecting sizes from the stream config. */

View file

@ -14,6 +14,7 @@
#include <math.h>
#include "formats.h"
#include "utils.h"
#include "v4l2_subdevice.h"
/**
@ -79,9 +80,8 @@ int CameraSensor::init()
if (entity_->function() != MEDIA_ENT_F_CAM_SENSOR) {
LOG(CameraSensor, Error)
<< "Invalid sensor function 0x"
<< std::hex << std::setfill('0') << std::setw(8)
<< entity_->function();
<< "Invalid sensor function "
<< utils::hex(entity_->function());
return -EINVAL;
}

View file

@ -549,8 +549,7 @@ const ControlValue &ControlList::get(unsigned int id) const
const auto ctrl = idmap_->find(id);
if (ctrl == idmap_->end()) {
LOG(Controls, Error)
<< std::hex << std::setfill('0')
<< "Control 0x" << std::setw(8) << id
<< "Control " << utils::hex(id)
<< " is not supported";
return zero;
}
@ -579,8 +578,7 @@ void ControlList::set(unsigned int id, const ControlValue &value)
const auto ctrl = idmap_->find(id);
if (ctrl == idmap_->end()) {
LOG(Controls, Error)
<< std::hex << std::setfill('0')
<< "Control 0x" << std::setw(8) << id
<< "Control 0x" << utils::hex(id)
<< " is not supported";
return;
}

View file

@ -10,6 +10,7 @@
#include <algorithm>
#include <chrono>
#include <memory>
#include <ostream>
#include <string>
#include <sys/time.h>
@ -63,6 +64,45 @@ using time_point = std::chrono::steady_clock::time_point;
struct timespec duration_to_timespec(const duration &value);
std::string time_point_to_string(const time_point &time);
#ifndef __DOXYGEN__
struct _hex {
uint64_t v;
unsigned int w;
};
std::basic_ostream<char, std::char_traits<char>> &
operator<<(std::basic_ostream<char, std::char_traits<char>> &stream, const _hex &h);
#endif
template<typename T>
_hex hex(T value, unsigned int width = 0);
#ifndef __DOXYGEN__
template<>
inline _hex hex<int32_t>(int32_t value, unsigned int width)
{
return { static_cast<uint64_t>(value), width ? width : 8 };
}
template<>
inline _hex hex<uint32_t>(uint32_t value, unsigned int width)
{
return { static_cast<uint64_t>(value), width ? width : 8 };
}
template<>
inline _hex hex<int64_t>(int64_t value, unsigned int width)
{
return { static_cast<uint64_t>(value), width ? width : 16 };
}
template<>
inline _hex hex<uint64_t>(uint64_t value, unsigned int width)
{
return { static_cast<uint64_t>(value), width ? width : 16 };
}
#endif
} /* namespace utils */
} /* namespace libcamera */

View file

@ -16,6 +16,7 @@
#include <libcamera/request.h>
#include "log.h"
#include "utils.h"
/**
* \file stream.h
@ -367,11 +368,7 @@ StreamConfiguration::StreamConfiguration(const StreamFormats &formats)
std::string StreamConfiguration::toString() const
{
std::stringstream ss;
ss.fill(0);
ss << size.toString() << "-0x" << std::hex << std::setw(8)
<< pixelFormat;
ss << size.toString() << "-" << utils::hex(pixelFormat);
return ss.str();
}

View file

@ -143,6 +143,45 @@ std::string time_point_to_string(const time_point &time)
return ossTimestamp.str();
}
std::basic_ostream<char, std::char_traits<char>> &
operator<<(std::basic_ostream<char, std::char_traits<char>> &stream, const _hex &h)
{
stream << "0x";
std::ostream::fmtflags flags = stream.setf(std::ios_base::hex,
std::ios_base::basefield);
std::streamsize width = stream.width(h.w);
char fill = stream.fill('0');
stream << h.v;
stream.flags(flags);
stream.width(width);
stream.fill(fill);
return stream;
}
/**
* \fn hex(T value, unsigned int width)
* \brief Write an hexadecimal value to an output string
* \param value The value
* \param width The width
*
* Return an object of unspecified type such that, if \a os is the name of an
* output stream of type std::ostream, and T is an integer type, then the
* expression
*
* \code{.cpp}
* os << utils::hex(value)
* \endcode
*
* will output the \a value to the stream in hexadecimal form with the base
* prefix and the filling character set to '0'. The field width is set to \a
* width if specified to a non-zero value, or to the native width of type T
* otherwise. The \a os stream configuration is not modified.
*/
} /* namespace utils */
} /* namespace libcamera */

View file

@ -21,6 +21,7 @@
#include "log.h"
#include "media_device.h"
#include "media_object.h"
#include "utils.h"
/**
* \file v4l2_subdevice.h
@ -76,10 +77,7 @@ LOG_DECLARE_CATEGORY(V4L2)
const std::string V4L2SubdeviceFormat::toString() const
{
std::stringstream ss;
ss.fill(0);
ss << size.toString() << "-0x" << std::hex << std::setw(4) << mbus_code;
ss << size.toString() << "-" << utils::hex(mbus_code, 4);
return ss.str();
}

View file

@ -23,6 +23,7 @@
#include "log.h"
#include "media_device.h"
#include "media_object.h"
#include "utils.h"
/**
* \file v4l2_videodevice.h
@ -239,10 +240,7 @@ LOG_DECLARE_CATEGORY(V4L2)
const std::string V4L2DeviceFormat::toString() const
{
std::stringstream ss;
ss.fill(0);
ss << size.toString() << "-0x" << std::hex << std::setw(8) << fourcc;
ss << size.toString() << "-" << utils::hex(fourcc);
return ss.str();
}

View file

@ -13,6 +13,7 @@
#include "camera_sensor.h"
#include "device_enumerator.h"
#include "media_device.h"
#include "utils.h"
#include "v4l2_subdevice.h"
#include "test.h"
@ -91,7 +92,7 @@ protected:
if (format.mbus_code != MEDIA_BUS_FMT_SBGGR10_1X10 ||
format.size != Size(4096, 2160)) {
cerr << "Failed to get a suitable format, expected 4096x2160-0x"
<< std::hex << MEDIA_BUS_FMT_SBGGR10_1X10
<< utils::hex(MEDIA_BUS_FMT_SBGGR10_1X10)
<< ", got " << format.toString() << endl;
return TestFail;
}

View file

@ -30,6 +30,7 @@ internal_tests = [
['threads', 'threads.cpp'],
['timer', 'timer.cpp'],
['timer-thread', 'timer-thread.cpp'],
['utils', 'utils.cpp'],
]
foreach t : public_tests

53
test/utils.cpp Normal file
View file

@ -0,0 +1,53 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (C) 2018, Google Inc.
*
* utils.cpp - Miscellaneous utility tests
*/
#include <iostream>
#include <sstream>
#include "test.h"
#include "utils.h"
using namespace std;
using namespace libcamera;
class UtilsTest : public Test
{
protected:
int run()
{
std::ostringstream os;
std::string ref;
os << utils::hex(static_cast<int32_t>(0x42)) << " ";
ref += "0x00000042 ";
os << utils::hex(static_cast<uint32_t>(0x42)) << " ";
ref += "0x00000042 ";
os << utils::hex(static_cast<int64_t>(0x42)) << " ";
ref += "0x0000000000000042 ";
os << utils::hex(static_cast<uint64_t>(0x42)) << " ";
ref += "0x0000000000000042 ";
os << utils::hex(static_cast<int32_t>(0x42), 4) << " ";
ref += "0x0042 ";
os << utils::hex(static_cast<uint32_t>(0x42), 1) << " ";
ref += "0x42 ";
os << utils::hex(static_cast<int64_t>(0x42), 4) << " ";
ref += "0x0042 ";
os << utils::hex(static_cast<uint64_t>(0x42), 1) << " ";
ref += "0x42 ";
std::string s = os.str();
if (s != ref) {
cerr << "utils::hex() test failed, expected '" << ref
<< "', got '" << s << "'";
return TestFail;
}
return TestPass;
}
};
TEST_REGISTER(UtilsTest)