Permalink
Fetching contributors…
Cannot retrieve contributors at this time
347 lines (281 sloc) 9.55 KB
/*
* Copyright (c) 2008-2018 the MRtrix3 contributors.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, you can obtain one at http://mozilla.org/MPL/2.0/
*
* MRtrix3 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* For more details, see http://www.mrtrix.org/
*/
#ifndef __mrtrix_h__
#define __mrtrix_h__
#include <climits>
#include <cstdio>
#include <cstdarg>
#include <cerrno>
#include <cassert>
#include <sstream>
#include <algorithm>
#include <cctype>
#include <iostream>
#include <array>
#include <string>
#include <cstring>
#include <cstdlib>
#include <limits>
#include <iomanip>
#include "types.h"
#include "exception.h"
namespace MR
{
//! read a line from the stream
/*! a replacement for the standard getline() function that also discards
* carriage returns if found at the end of the line. */
inline std::istream& getline (std::istream& stream, std::string& string)
{
std::getline (stream, string);
if (string.size() > 0)
if (string[string.size()-1] == 015)
string.resize (string.size()-1);
return stream;
}
template <typename X, typename ReturnType = int>
struct max_digits { NOMEMALIGN
static constexpr int value () { return 0; }
};
template <typename X>
struct max_digits<X, typename std::enable_if<std::is_fundamental<X>::value, int>::type> { NOMEMALIGN
static constexpr int value () { return std::numeric_limits<X>::max_digits10; }
};
template <typename X>
struct max_digits<X, typename std::enable_if<std::is_fundamental<typename X::Scalar>::value, int>::type> { NOMEMALIGN
static constexpr int value () { return std::numeric_limits<typename X::Scalar>::max_digits10; }
};
template <typename X>
struct max_digits<X, typename std::enable_if<std::is_fundamental<typename X::value_type>::value && !std::is_fundamental<typename X::Scalar>::value, int>::type> { NOMEMALIGN
static constexpr int value () { return std::numeric_limits<typename X::value_type>::max_digits10; }
};
template <class T> inline std::string str (const T& value, int precision = 0)
{
std::ostringstream stream;
if (precision)
stream.precision (precision);
else if (max_digits<T>::value())
stream.precision (max_digits<T>::value());
stream << value;
if (stream.fail())
throw Exception ("error converting value to string");
return stream.str();
}
//! add a line to a string, taking care of inserting a newline if needed
inline std::string& add_line (std::string& original, const std::string& new_line)
{
return original.size() ? (original += "\n" + new_line) : ( original = new_line );
}
//! convert a long string to 'beginningofstring...endofstring' for display
inline std::string shorten (const std::string& text, size_t longest = 40, size_t prefix = 10)
{
if (text.size() > longest)
return (text.substr (0,prefix) + "..." + text.substr (text.size()-longest+prefix+3));
else
return text;
}
//! return lowercase version of string
inline std::string lowercase (const std::string& string)
{
std::string ret;
ret.resize (string.size());
transform (string.begin(), string.end(), ret.begin(), tolower);
return ret;
}
//! return uppercase version of string
inline std::string uppercase (const std::string& string)
{
std::string ret;
ret.resize (string.size());
transform (string.begin(), string.end(), ret.begin(), toupper);
return ret;
}
template <class T> inline T to (const std::string& string)
{
std::istringstream stream (string);
T value;
stream >> value;
if (stream.fail()) {
const std::string lstring = lowercase (string);
if (lstring == "nan")
return std::numeric_limits<T>::quiet_NaN();
else if (lstring == "-nan")
return -std::numeric_limits<T>::quiet_NaN();
else if (lstring == "inf")
return std::numeric_limits<T>::infinity();
else if (lstring == "-inf")
return -std::numeric_limits<T>::infinity();
throw Exception ("error converting string \"" + string + "\"");
}
return value;
}
inline std::string printf (const char* format, ...)
{
size_t len = 0;
va_list list1, list2;
va_start (list1, format);
va_copy (list2, list1);
len = vsnprintf (nullptr, 0, format, list1) + 1;
va_end (list1);
VLA(buf, char, len);
vsnprintf (buf, len, format, list2);
va_end (list2);
return buf;
}
inline std::string strip (const std::string& string, const std::string& ws = {" \0\t\n", 4}, bool left = true, bool right = true)
{
std::string::size_type start = (left ? string.find_first_not_of (ws) : 0);
if (start == std::string::npos)
return "";
std::string::size_type end = (right ? string.find_last_not_of (ws) + 1 : std::string::npos);
return string.substr (start, end - start);
}
inline void replace (std::string& string, char orig, char final)
{
for (auto& c: string)
if (c == orig) c = final;
}
inline void replace (std::string& str, const std::string& from, const std::string& to)
{
if (from.empty()) return;
size_t start_pos = 0;
while ((start_pos = str.find (from, start_pos)) != std::string::npos) {
str.replace (start_pos, from.length(), to);
start_pos += to.length();
}
}
vector<std::string> split (
const std::string& string,
const char* delimiters = " \t\n",
bool ignore_empty_fields = false,
size_t num = std::numeric_limits<size_t>::max());
inline vector<std::string> split_lines (
const std::string& string,
bool ignore_empty_fields = true,
size_t num = std::numeric_limits<size_t>::max())
{
return split (string, "\n", ignore_empty_fields, num);
}
inline std::string join (const vector<std::string>& V, const std::string& delimiter)
{
std::string ret;
if (V.empty())
return ret;
ret = V[0];
for (vector<std::string>::const_iterator i = V.begin() +1; i != V.end(); ++i)
ret += delimiter + *i;
return ret;
}
template <typename T>
inline std::string join (const vector<T>& V, const std::string& delimiter)
{
std::string ret;
if (V.empty())
return ret;
ret = str(V[0]);
for (typename vector<T>::const_iterator i = V.begin() +1; i != V.end(); ++i)
ret += delimiter + str(*i);
return ret;
}
inline std::string join (const char* const* null_terminated_array, const std::string& delimiter)
{
std::string ret;
if (!null_terminated_array)
return ret;
ret = null_terminated_array[0];
for (const char* const* p = null_terminated_array+1; *p; ++p)
ret += delimiter + *p;
return ret;
}
vector<default_type> parse_floats (const std::string& spec);
vector<int> parse_ints (const std::string& spec, int last = std::numeric_limits<int>::max());
/*
inline int round (default_type x)
{
return int (x + (x > 0.0 ? 0.5 : -0.5));
}
*/
/**********************************************************************
specialisations to convert complex numbers to/from text:
**********************************************************************/
template <> inline std::string str<cfloat> (const cfloat& value, int precision)
{
std::ostringstream stream;
if (precision > 0)
stream.precision (precision);
stream << value.real();
if (value.imag())
stream << std::showpos << value.imag() << "i";
if (stream.fail())
throw Exception ("error converting value to string");
return stream.str();
}
template <> inline cfloat to<cfloat> (const std::string& string)
{
std::istringstream stream (string);
float real, imag;
stream >> real;
if (stream.fail())
throw Exception ("error converting string \"" + string + "\"");
if (stream.eof())
return cfloat (real, 0.0f);
if (stream.peek() == 'i' || stream.peek() == 'j')
return cfloat (0.0f, real);
stream >> imag;
if (stream.fail())
return cfloat (real, 0.0f);
else if (stream.peek() != 'i' && stream.peek() != 'j')
throw Exception ("error converting string \"" + string + "\"");
return cfloat (real, imag);
}
template <> inline std::string str<cdouble> (const cdouble& value, int precision)
{
std::ostringstream stream;
if (precision > 0)
stream.precision (precision);
stream << value.real();
if (value.imag())
stream << std::showpos << value.imag() << "i";
if (stream.fail())
throw Exception ("error converting value to string");
return stream.str();
}
template <> inline cdouble to<cdouble> (const std::string& string)
{
std::istringstream stream (string);
double real, imag;
stream >> real;
if (stream.fail())
throw Exception ("error converting string \"" + string + "\"");
if (stream.eof())
return cdouble (real, 0.0);
if (stream.peek() == 'i' || stream.peek() == 'j')
return cdouble (0.0, real);
stream >> imag;
if (stream.fail())
return cdouble (real, 0.0);
else if (stream.peek() != 'i' && stream.peek() != 'j')
throw Exception ("error converting string \"" + string + "\"");
return cdouble (real, imag);
}
template <> inline bool to<bool> (const std::string& string)
{
std::string value = lowercase (string);
if (value == "true" || value == "yes")
return true;
if (value == "false" || value == "no")
return false;
return to<int> (value);
}
}
#endif