Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 8 additions & 32 deletions src/Ascii_Writer/Ascii_Writer.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -14,29 +14,6 @@
#include "../Format_Packet.hxx"
#include "../data_size.hxx"

namespace {


void apply_format_packet(std::ostream &stream, const tablator::Format_Packet &fmt) {
switch (fmt.flag_) {
case 'f':
stream << std::fixed << std::setprecision(fmt.precision_);
break;
case 'e':
stream << std::scientific << std::setprecision(fmt.precision_);
break;
case 'g':
case '\0':
default:
stream << std::defaultfloat << std::setprecision(fmt.precision_);
break;
}
}


} // namespace


namespace tablator {
// Declare static constexpr class members.
constexpr const char Ascii_Writer::DEFAULT_SEPARATOR;
Expand All @@ -62,8 +39,7 @@ void Ascii_Writer::write_type_as_ascii(std::ostream &os,
if (type != Data_Type::CHAR && array_size != 1) {
for (size_t n = 0; n < array_size; ++n) {
write_array_unit_as_ascii(os, format_packet, 1,
data + n * get_data_size(type),
options);
data + n * get_data_size(type), options);

if (n != array_size - 1) {
os << separator;
Expand All @@ -85,8 +61,7 @@ void Ascii_Writer::write_type_as_ascii_expand_array(
for (size_t n = 0; n < array_size; ++n) {
os << std::setw(col_width);
write_array_unit_as_ascii(os, format_packet, 1,
data + n * get_data_size(type),
options);
data + n * get_data_size(type), options);

if (n != array_size - 1) {
os << IPAC_COLUMN_SEPARATOR;
Expand Down Expand Up @@ -138,17 +113,18 @@ void Ascii_Writer::write_array_unit_as_ascii(std::ostream &os,
os << *reinterpret_cast<const uint64_t *>(data);
} break;
case Data_Type::FLOAT32_LE: {
apply_format_packet(os, format_packet);
os << *reinterpret_cast<const float *>(data);
format_packet.apply_to_stream(os);
os << *reinterpret_cast<const float *>(data);
} break;
case Data_Type::FLOAT64_LE: {
double value_doub = *reinterpret_cast<const double *>(data);
if (options.is_trim_decimal_runs()) {
os << Decimal_String_Trimmer::get_decimal_string(
*reinterpret_cast<const double *>(data),
value_doub, format_packet.get_formatted_value(value_doub),
options.min_run_length_for_trim_);
} else {
apply_format_packet(os, format_packet);
os << *reinterpret_cast<const double *>(data);
format_packet.apply_to_stream(os);
os << value_doub;
}
} break;
case Data_Type::CHAR:
Expand Down
5 changes: 2 additions & 3 deletions src/Column.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -98,13 +98,12 @@ public:
return tablator::get_data_size(type_) * array_size_;
}

inline Format_Packet get_format_packet() const { return format_packet_; }
inline const Format_Packet &get_format_packet() const { return format_packet_; }

private:
static std::string extract_format_str(const Field_Properties &field_properties) {
const auto &field_prop_attributes = field_properties.get_attributes();
const auto format_iter =
field_prop_attributes.find(ATTR_IRSA_FORMAT);
const auto format_iter = field_prop_attributes.find(ATTR_IRSA_FORMAT);
if (format_iter != field_prop_attributes.end()) {
return format_iter->second;
}
Expand Down
8 changes: 5 additions & 3 deletions src/Decimal_String_Trimmer.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

#include <iostream>


namespace tablator {

namespace Decimal_String_Trimmer {
Expand All @@ -12,11 +11,14 @@ namespace Decimal_String_Trimmer {
// decimal point in the decimal representation of doub_value. If it
// finds such a run, it rounds up or down accordingly and truncates
// the string.
const std::string get_decimal_string(double doub_value, ushort min_run_length_for_trim);
const std::string get_decimal_string(double doub_value,
const std::string &orig_doub_str,
ushort min_run_length_for_trim);


// This function returns the length of the string returned by get_decimal_string().
size_t get_decimal_string_length(double doub_value, ushort min_run_length_for_trim);
size_t get_decimal_string_length(double doub_value, const std::string &orig_doub_str,
ushort min_run_length_for_trim);

} // namespace Decimal_String_Trimmer

Expand Down
48 changes: 27 additions & 21 deletions src/Decimal_String_Trimmer/Decimal_String_Trimmer.cxx
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
#include "../Decimal_String_Trimmer.hxx"

#include <cassert>
#include <sstream>

#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>

#include "../Decimal_String_Trimmer.hxx"


namespace {

//==============
Expand All @@ -15,29 +14,33 @@ namespace {

class Trimmability_Packet {
public:
Trimmability_Packet(double value_doub, ushort min_run_length_for_trim)
Trimmability_Packet(double value_doub, const std::string &orig_value_str,
ushort min_run_length_for_trim)
: min_run_length_for_trim_(min_run_length_for_trim) {
// Check for negative value.
value_doub_ = value_doub;
is_neg_ = (value_doub < 0);

value_str_ = boost::lexical_cast<std::string>(value_doub);
value_str_ = orig_value_str;
abs_value_str_ = is_neg_ ? value_str_.substr(1) : value_str_;

// Check for scientific notation ("a.bbbbe-cc").
e_pos_ = abs_value_str_.find("e");
got_exp_ = (e_pos_ != std::string::npos);

abs_str_len_ = abs_value_str_.size();
abs_coeff_str_len_ = got_exp_ ? e_pos_ : abs_str_len_;

exp_str_ = got_exp_ ? abs_value_str_.substr(e_pos_) : "";
adjusted_exp_str_.assign(exp_str_); // Adjust later as needed.

// Prepare to check for runs of 0s or of 9s starting to the right
// of the decimal point and on or to the right of the first
// non-zero digit.
anchor_pos_ = find_anchor_pos(abs_value_str_, abs_coeff_str_len_);

bool keep_looking =
is_candidate_for_adjustment(anchor_pos_, abs_coeff_str_len_);

if (keep_looking) {
// Set default values of these variables which will then capture
// the return value of get_rounding_info_for_double().
Expand All @@ -62,7 +65,7 @@ class Trimmability_Packet {

//================================================

const std::string get_possibly_trimmed_string() const {
const std::string get_possibly_trimmed_string() {
if (!is_trimmable_) {
return value_str_;
}
Expand All @@ -81,8 +84,6 @@ class Trimmability_Packet {

std::string abs_ret_coeff_str =
abs_coeff_str_.substr(0, adjusted_abs_coeff_str_len_);
std::string exp_str_ = got_exp_ ? abs_value_str_.substr(e_pos_) : "";


if (!got_run_of_9s_) {
// The run is of 0s; all that's needed is to truncate and, if
Expand Down Expand Up @@ -122,9 +123,14 @@ class Trimmability_Packet {
// coeff_str was 9.9999912, adjusted_abs_coeff_str would be
// 10.0). This next call produces a string in proper
// scientific notation format, replacing e.g. 10.0e-5 with
// 1.0e-4.
return sign_str +
standardize_scientific_notation(adjusted_abs_coeff_str, exp_str_);
// 1.00e-4.
const auto standardized_str =
standardize_scientific_notation(adjusted_abs_coeff_str, exp_str_);

size_t adjusted_e_pos = standardized_str.find("e");
adjusted_exp_str_ = standardized_str.substr(adjusted_e_pos);

return sign_str + standardized_str;
}
return sign_str + adjusted_abs_coeff_str;
}
Expand All @@ -133,12 +139,8 @@ class Trimmability_Packet {

size_t get_possibly_trimmed_length() const {
if (is_trimmable_) {
static const short MAX_EXP_LEN = 4; // "e-cd"
// Don't bother estimating length of possibly adjusted exp_str.
size_t max_exp_len = got_exp_ ? MAX_EXP_LEN : 0;
short sign_len = is_neg_ ? 1 : 0;

return sign_len + adjusted_abs_coeff_str_len_ + max_exp_len;
return sign_len + adjusted_abs_coeff_str_len_ + adjusted_exp_str_.size();
}
return value_str_.size();
}
Expand Down Expand Up @@ -278,6 +280,8 @@ class Trimmability_Packet {

std::string value_str_;
std::string abs_value_str_;
std::string exp_str_;
std::string adjusted_exp_str_;

size_t e_pos_;
bool got_exp_;
Expand Down Expand Up @@ -308,16 +312,18 @@ namespace tablator {
// the string.

const std::string Decimal_String_Trimmer::get_decimal_string(
double doub_value, ushort min_run_length_for_trim) {
Trimmability_Packet trim_packet(doub_value, min_run_length_for_trim);
double doub_value, const std::string &orig_doub_str,
ushort min_run_length_for_trim) {
Trimmability_Packet trim_packet(doub_value, orig_doub_str, min_run_length_for_trim);
return trim_packet.get_possibly_trimmed_string();
}

// This function returns the length of the string returned by get_decimal_string().

size_t tablator::Decimal_String_Trimmer::get_decimal_string_length(
double doub_value, ushort min_run_length_for_trim) {
Trimmability_Packet trim_packet(doub_value, min_run_length_for_trim);
double doub_value, const std::string &orig_doub_str,
ushort min_run_length_for_trim) {
Trimmability_Packet trim_packet(doub_value, orig_doub_str, min_run_length_for_trim);
return trim_packet.get_possibly_trimmed_length();
}

Expand Down
56 changes: 56 additions & 0 deletions src/Format_Packet.hxx
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#pragma once

#include <iomanip>
#include <iostream>

#include "data_size.hxx"

namespace tablator {
Expand Down Expand Up @@ -63,6 +66,59 @@ struct Format_Packet {

Format_Packet() : Format_Packet("", Data_Type::CHAR) {}

//=============================================

void apply_to_stream(std::ostream &os) const {
switch (flag_) {
case 'f':
os << std::fixed << std::setprecision(precision_);
break;
case 'e':
os << std::scientific << std::setprecision(precision_);
break;
default:
os << std::defaultfloat << std::setprecision(precision_);
break;
}
}

//=============================================

template <typename T, typename = std::enable_if_t<std::is_floating_point_v<T>>>
std::string get_formatted_value(T value) const {
std::ostringstream oss;
apply_to_stream(oss);
oss << value;
return oss.str();
}

//=============================================

size_t get_max_strlen() const {
// https://stackoverflow.com/questions/2151302/counting-digits-in-a-float
static size_t MAX_FLOAT32_STRLEN = 15;
static size_t MAX_FLOAT64_STRLEN = 24;

static size_t MAX_FLOAT32_EXPONENT_STRLEN = 4;
static size_t MAX_FLOAT64_EXPONENT_STRLEN = 5;

size_t max_strlen;
if (data_type_ == Data_Type::FLOAT32_LE) {
max_strlen = MAX_FLOAT32_STRLEN;
if (flag_ == 'e') {
max_strlen += MAX_FLOAT32_EXPONENT_STRLEN;
}
} else {
max_strlen = MAX_FLOAT64_STRLEN;
if (flag_ == 'e') {
max_strlen += MAX_FLOAT64_EXPONENT_STRLEN;
}
}
return max_strlen;
}

//=============================================

Data_Type data_type_;
uint precision_;
char flag_;
Expand Down
Loading