Skip to content

Commit

Permalink
Static analysis fixes, format
Browse files Browse the repository at this point in the history
* Fix uninitialized member variables
* Explicitly std::move a string where applicable
* Use map::find instead of map::count to search for single key
* Restore ostream format after hex printout
* Some unsigned literals
* clang-format
  • Loading branch information
windytan committed Jun 16, 2024
1 parent d3d523a commit 573c08f
Show file tree
Hide file tree
Showing 15 changed files with 364 additions and 350 deletions.
18 changes: 10 additions & 8 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,26 @@

## HEAD

* Maintainability changes:
* Maintainability:
* Migrate build system from autotools to meson (#90)
* Add GitHub Workflows CI builds for macOS and Windows via MSYS2/MinGW + Cygwin
* Add basic Catch2 unit tests (#84)
* Add .clang-format (not automated)
* Remove unmaintained build options for non-liquid, non-TMC builds
* Fix compiler warnings and other code cleanup
* Fix compiler warnings, issues identified via static analysis, and other code cleanup
* New features:
* Add support for Enhanced RadioText (eRT)
* Add support for Long PS in Group 15A (#104)
* UX changes:
* Breaking: Print a warning to stderr if the raw MPX input sample rate is
not specified
* Improve error reporting in general
* Add `--output hex` (same as `--output-hex`) to mirror `--input hex`
* Add support for Enhanced RadioText (eRT)
* Add support for Long PS in Group 15A (#104)
* Fix detection of invalid date/time (timestamps >2000 years ago)
* Noise resistance improvements:
* Require three (instead of two) repeats of a new PI before accepting it
* Require three (instead of two) synchronization pulses before locking
* Fixes:
* Fix detection of invalid date/time (timestamps >2000 years ago)
* Noise resistance improvements:
* Require three (instead of two) repeats of a new PI before accepting it
* Require three (instead of two) synchronization pulses before locking

## 0.21 (2024-01-26)

Expand Down
19 changes: 10 additions & 9 deletions src/common.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,28 +19,29 @@

namespace redsea {

std::string getTimePointString(
const std::chrono::time_point<std::chrono::system_clock>& timepoint,
const std::string& format) {

std::string getTimePointString(const std::chrono::time_point<std::chrono::system_clock>& timepoint,
const std::string& format) {
// This is done to ensure we get truncation and not rounding to integer seconds
const auto seconds_since_epoch(
std::chrono::duration_cast<std::chrono::seconds>(timepoint.time_since_epoch()));
const std::time_t t = std::chrono::system_clock::to_time_t(std::chrono::system_clock::time_point(seconds_since_epoch));
const std::time_t t = std::chrono::system_clock::to_time_t(
std::chrono::system_clock::time_point(seconds_since_epoch));

std::string format_with_fractional(format);
const std::size_t found = format_with_fractional.find("%f");
if (found != std::string::npos) {
const int ms = (std::chrono::duration_cast<std::chrono::milliseconds>(timepoint.time_since_epoch() -
seconds_since_epoch)).count();
const int hundredths = (ms / 10) % 10;
const int ms = (std::chrono::duration_cast<std::chrono::milliseconds>(
timepoint.time_since_epoch() - seconds_since_epoch))
.count();
const int hundredths = (ms / 10) % 10;
const int tenths = (ms / 100) % 10;

format_with_fractional.replace(found, 2, std::to_string(tenths) + std::to_string(hundredths));
}

char buffer[64];
if (std::strftime(buffer, sizeof(buffer), format_with_fractional.c_str(), std::localtime(&t)) == 0) {
if (std::strftime(buffer, sizeof(buffer), format_with_fractional.c_str(), std::localtime(&t)) ==
0) {
return "(format error)";
}

Expand Down
26 changes: 14 additions & 12 deletions src/groups.cc
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,6 @@ uint16_t Group::getBlock(eBlockNumber block_num) const {
return blocks_[block_num].data;
}

uint16_t Group::getBlock1() const {
return blocks_[0].data;
}

uint16_t Group::getBlock2() const {
return blocks_[1].data;
}
Expand Down Expand Up @@ -191,6 +187,9 @@ void Group::setAverageBLER(float bler) {
*
*/
void Group::printHex(std::ostream& stream) const {
std::ios old_stream_state(nullptr);
old_stream_state.copyfmt(stream);

stream.fill('0');
stream.setf(std::ios_base::uppercase);

Expand All @@ -204,6 +203,9 @@ void Group::printHex(std::ostream& stream) const {
if (block_num != BLOCK4)
stream << " ";
}

// Restore ostream format
stream.copyfmt(old_stream_state);
}

/*
Expand Down Expand Up @@ -303,7 +305,7 @@ void Station::updateAndPrint(const Group& group, std::ostream& stream) {
decodeType15B(group);

// Other groups can be reassigned for ODA by a 3A group
} else if (oda_app_for_group_.count(type) > 0) {
} else if (oda_app_for_group_.find(type) != oda_app_for_group_.end()) {
decodeODAGroup(group);

// Below: Groups that could optionally be used for ODA but have
Expand Down Expand Up @@ -539,8 +541,8 @@ void Station::decodeType2(const Group& group) {
if (!(group.has(BLOCK3) && group.has(BLOCK4)))
return;

const size_t radiotext_position =
getBits<4>(group.getBlock2(), 0) * (group.getType().version == GroupType::Version::A ? 4 : 2);
const size_t radiotext_position = getBits<4>(group.getBlock2(), 0) *
(group.getType().version == GroupType::Version::A ? 4UL : 2UL);

const bool is_ab_changed = radiotext_.isABChanged(getBits<1>(group.getBlock2(), 4));

Expand Down Expand Up @@ -587,7 +589,7 @@ void Station::decodeType2(const Group& group) {

// Method 3 was used instead (and was confirmed by a repeat).
} else if (has_potentially_complete_message) {
json_["*SORT04*radiotext"] = rtrim(potentially_complete_message);
json_["*SORT04*radiotext"] = rtrim(std::move(potentially_complete_message));

// The string is not complete yet, but user wants to see it anyway.
} else if (options_.show_partial && rtrim(radiotext_.text.str()).length() > 0) {
Expand Down Expand Up @@ -838,8 +840,8 @@ void Station::decodeType14(const Group& group) {
case 1:
case 2:
case 3:
if (eon_ps_names_.count(on_pi) == 0)
eon_ps_names_[on_pi] = RDSString(8);
if (eon_ps_names_.find(on_pi) == eon_ps_names_.end())
eon_ps_names_.emplace(on_pi, RDSString(8));

eon_ps_names_[on_pi].set(2 * eon_variant, getBits<8>(group.getBlock3(), 8));
eon_ps_names_[on_pi].set(2 * eon_variant + 1, getBits<8>(group.getBlock3(), 0));
Expand Down Expand Up @@ -942,7 +944,7 @@ void Station::decodeType15B(const Group& group) {

/* Open Data Application */
void Station::decodeODAGroup(const Group& group) {
if (oda_app_for_group_.count(group.getType()) == 0) {
if (oda_app_for_group_.find(group.getType()) == oda_app_for_group_.end()) {
json_["unknown_oda"]["raw_data"] =
getHexString(group.getBlock(BLOCK2) & 0b11111, 2) + " " +
(group.has(BLOCK3) ? getHexString(group.getBlock(BLOCK3), 4) : "----") + " " +
Expand Down Expand Up @@ -1088,7 +1090,7 @@ void Station::parseDAB(const Group& group) {
// clang-format on
});

if (dab_channels.count(freq) != 0) {
if (dab_channels.find(freq) != dab_channels.end()) {
json_["dab"]["channel"] = dab_channels.at(freq);
}

Expand Down
4 changes: 2 additions & 2 deletions src/input.cc
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ Group readTEFGroup(const Options& options) {
const int64_t data = std::stol(line, nullptr, 16);
block1.data = data & 0xFFFF;
block1.is_received = true;
} catch (std::exception& e) {
} catch (const std::exception&) {
}
group.setBlock(BLOCK1, block1);
} else if (line.substr(0, 1) == "R") {
Expand All @@ -249,7 +249,7 @@ Group readTEFGroup(const Options& options) {
line = line.substr(1);
data = std::stol(line, nullptr, 16);
rdsErr = (data & 0xFF);
} catch (std::exception& e) {
} catch (const std::exception&) {
}
for (const auto blockNum : { BLOCK2, BLOCK3, BLOCK4 }) {
Block block;
Expand Down
38 changes: 19 additions & 19 deletions src/input.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,15 @@

namespace redsea {

constexpr int kInputChunkSize = 8192;
constexpr int kInputChunkSize = 8192;
constexpr float kMaxResampleRatio = kTargetSampleRate_Hz / kMinimumSampleRate_Hz;
constexpr int kBufferSize = static_cast<int>(kInputChunkSize * kMaxResampleRatio) + 1;
constexpr int kBufferSize = static_cast<int>(kInputChunkSize * kMaxResampleRatio) + 1;

template<int N=kBufferSize>
template <int N = kBufferSize>
class MPXBuffer {
public:
std::array<float, N> data;
size_t used_size;
std::array<float, N> data{};
size_t used_size{};
std::chrono::time_point<std::chrono::system_clock> time_received;
};

Expand All @@ -59,18 +59,18 @@ class MPXReader {
int getNumChannels() const;

private:
int num_channels_ { 0 };
sf_count_t chunk_size_;
bool is_eof_ { true };
bool is_error_ { false };
bool feed_thru_ { false };
std::string filename_ { "" };
MPXBuffer<> buffer_;
MPXBuffer<> buffer_singlechan_;
SF_INFO sfinfo_ { 0, 0, 0, 0, 0, 0 };
SNDFILE* file_ { nullptr };
SNDFILE* outfile_ { nullptr };
sf_count_t num_read_ { 0 };
int num_channels_{0};
sf_count_t chunk_size_{0};
bool is_eof_{true};
bool is_error_{false};
bool feed_thru_{false};
std::string filename_{""};
MPXBuffer<> buffer_{};
MPXBuffer<> buffer_singlechan_{};
SF_INFO sfinfo_{0, 0, 0, 0, 0, 0};
SNDFILE* file_{nullptr};
SNDFILE* outfile_{nullptr};
sf_count_t num_read_{0};
};

class AsciiBitReader {
Expand All @@ -81,8 +81,8 @@ class AsciiBitReader {
bool eof() const;

private:
bool is_eof_ { false };
bool feed_thru_ { false };
bool is_eof_{false};
bool feed_thru_{false};
};

Group readHexGroup(const Options& options);
Expand Down
Loading

0 comments on commit 573c08f

Please sign in to comment.