aboutsummaryrefslogblamecommitdiffstats
path: root/util/string/cast.h
blob: 3d94ecb0de98ddbd7e2d6bdb8bfd0f25906cff2f (plain) (tree)
1
2
3
4
5
6
7
8
9
            
 
                                 
                            
                               
                                
                                
                                    
                                    






                                                
   


                                                                                      
                                                           
                                                       


                                             

                                                                                    
                         








                                                                                        


                                                                 



                                                                                                            
                     
                                                                                                
                                                                                                         
                               
 

                                     
                                               
                          
                                                                  



                                
                                               


                               






                                 
                                     
                                   
 
                                                                                       
 
                                                           

             
                                                     

             
                                        

             
                                  


             
                            
                  
                                                
 
                                                            

             
                                                      

             

                                                       
  
                   
        










                      
                                                
 
                                                    

                                          
                                        
                                                                        

                  
                                          
                                               

                  
                                       
                                               





                                               
           
                                                      

             
                  
                                          
                                                                               

                  
                                            
                                                        
 

























                                                                                 
                                                                                       


                                                                          
                                                                          
 
















                                                                       
                                                                                 
 







                                                                                         
                                                           
                                                        

                  
                                                        
                                                        

                  



                                                            
                                                           
                                                        

                  
                                                             
                                                        
 




























                                                          
                                                                                     
                                                             
 



                                                                              
                                                                       









                                                                        
                                                                    
                                                  
 



                                                             
                                                      

                                            

                                                       


                                               
                                 
                                                                                                                           

                  
                                                                
 

                                                                   
                                                                  
                                                              
 



                                                 
                                                                                
 
                                                   
                                                             
 










                                                                     
#pragma once

#include <util/system/defaults.h>
#include <util/stream/str.h>
#include <util/generic/maybe.h>
#include <util/generic/string.h>
#include <util/generic/strbuf.h>
#include <util/generic/typetraits.h>
#include <util/generic/yexception.h>

/*
 * specialized for all arithmetic types
 */

template <class T>
size_t ToStringImpl(T t, char* buf, size_t len);

/**
 * Converts @c t to string writing not more than @c len bytes to output buffer @c buf.
 * No NULL terminator appended! Throws exception on buffer overflow.
 * @return number of bytes written
 */
template <class T>
inline size_t ToString(const T& t, char* buf, size_t len) {
    using TParam = typename TTypeTraits<T>::TFuncParam;

    return ToStringImpl<TParam>(t, buf, len);
}

/**
 * Floating point to string conversion mode, values are enforced by `dtoa_impl.cpp`.
 */
enum EFloatToStringMode {
    /** 0.1f -> "0.1", 0.12345678f -> "0.12345678", ignores ndigits. */
    PREC_AUTO = 0,

    /** "%g" mode, writes up to the given number of significant digits:
     *  0.1f -> "0.1", 0.12345678f -> "0.123457" for ndigits=6, 1.2e-06f -> "1.2e-06" */
    PREC_NDIGITS = 2,

    /** "%f" mode, writes the given number of digits after decimal point:
     *  0.1f -> "0.100000", 1.2e-06f -> "0.000001" for ndigits=6 */
    PREC_POINT_DIGITS = 3,

    /** same as PREC_POINT_DIGITS, but stripping trailing zeroes:
     * 0.1f for ndgigits=6 -> "0.1" */
    PREC_POINT_DIGITS_STRIP_ZEROES = 4
};

size_t FloatToString(float t, char* buf, size_t len, EFloatToStringMode mode = PREC_AUTO, int ndigits = 0);
size_t FloatToString(double t, char* buf, size_t len, EFloatToStringMode mode = PREC_AUTO, int ndigits = 0);

template <typename T>
inline TString FloatToString(const T& t, EFloatToStringMode mode = PREC_AUTO, int ndigits = 0) {
    char buf[512]; // Max<double>() with mode = PREC_POINT_DIGITS has 309 digits before the decimal point
    size_t count = FloatToString(t, buf, sizeof(buf), mode, ndigits);
    return TString(buf, count);
}

namespace NPrivate {
    template <class T, bool isSimple>
    struct TToString {
        static inline TString Cvt(const T& t) {
            char buf[512];

            return TString(buf, ToString<T>(t, buf, sizeof(buf)));
        }
    };

    template <class T>
    struct TToString<T, false> {
        static inline TString Cvt(const T& t) {
            TString s;
            TStringOutput o(s);
            o << t;
            return s;
        }
    };
}

/*
 * some clever implementations...
 */
template <class T>
inline TString ToString(const T& t) {
    using TR = std::remove_cv_t<T>;

    return ::NPrivate::TToString<TR, std::is_arithmetic<TR>::value>::Cvt((const TR&)t);
}

inline const TString& ToString(const TString& s) noexcept {
    return s;
}

inline const TString& ToString(TString& s) noexcept {
    return s;
}

inline TString ToString(const char* s) {
    return s;
}

inline TString ToString(char* s) {
    return s;
}

/*
 * Wrapper for wide strings.
 */
template <class T>
inline TUtf16String ToWtring(const T& t) {
    return TUtf16String::FromAscii(ToString(t));
}

inline const TUtf16String& ToWtring(const TUtf16String& w) {
    return w;
}

inline const TUtf16String& ToWtring(TUtf16String& w) {
    return w;
}

struct TFromStringException: public TBadCastException {
};

/*
 * specialized for:
 *  bool
 *  short
 *  unsigned short
 *  int
 *  unsigned int
 *  long
 *  unsigned long
 *  long long
 *  unsigned long long
 *  float
 *  double
 *  long double
 */
template <typename T, typename TChar>
T FromStringImpl(const TChar* data, size_t len);

template <typename T, typename TChar>
inline T FromString(const TChar* data, size_t len) {
    return ::FromStringImpl<T>(data, len);
}

template <typename T, typename TChar>
inline T FromString(const TChar* data) {
    return ::FromString<T>(data, std::char_traits<TChar>::length(data));
}

template <class T>
inline T FromString(const TStringBuf& s) {
    return ::FromString<T>(s.data(), s.size());
}

template <class T>
inline T FromString(const TString& s) {
    return ::FromString<T>(s.data(), s.size());
}

template <class T>
inline T FromString(const std::string& s) {
    return ::FromString<T>(s.data(), s.size());
}

template <>
inline TString FromString<TString>(const TString& s) {
    return s;
}

template <class T>
inline T FromString(const TWtringBuf& s) {
    return ::FromString<T, typename TWtringBuf::char_type>(s.data(), s.size());
}

template <class T>
inline T FromString(const TUtf16String& s) {
    return ::FromString<T, wchar16>(s.data(), s.size());
}

namespace NPrivate {
    template <typename TChar>
    class TFromString {
        const TChar* const Data;
        const size_t Len;

    public:
        inline TFromString(const TChar* data, size_t len)
            : Data(data)
            , Len(len)
        {
        }

        template <typename T>
        inline operator T() const {
            return FromString<T, TChar>(Data, Len);
        }
    };
}

template <typename TChar>
inline ::NPrivate::TFromString<TChar> FromString(const TChar* data, size_t len) {
    return ::NPrivate::TFromString<TChar>(data, len);
}

template <typename TChar>
inline ::NPrivate::TFromString<TChar> FromString(const TChar* data) {
    return ::NPrivate::TFromString<TChar>(data, std::char_traits<TChar>::length(data));
}

template <typename T>
inline ::NPrivate::TFromString<typename T::TChar> FromString(const T& s) {
    return ::NPrivate::TFromString<typename T::TChar>(s.data(), s.size());
}

// Conversion exception free versions
template <typename T, typename TChar>
bool TryFromStringImpl(const TChar* data, size_t len, T& result);

/**
 * @param data Source string buffer pointer
 * @param len Source string length, in characters
 * @param result Place to store conversion result value.
 * If conversion error occurs, no value stored in @c result
 * @return @c true in case of successful conversion, @c false otherwise
 **/
template <typename T, typename TChar>
inline bool TryFromString(const TChar* data, size_t len, T& result) {
    return TryFromStringImpl<T>(data, len, result);
}

template <typename T, typename TChar>
inline bool TryFromString(const TChar* data, T& result) {
    return TryFromString<T>(data, std::char_traits<TChar>::length(data), result);
}

template <class T, class TChar>
inline bool TryFromString(const TChar* data, const size_t len, T& result, const T& def) {
    if (TryFromString<T>(data, len, result)) {
        return true;
    }
    result = def;
    return false;
}

template <class T>
inline bool TryFromString(const TStringBuf& s, T& result) {
    return TryFromString<T>(s.data(), s.size(), result);
}

template <class T>
inline bool TryFromString(const TString& s, T& result) {
    return TryFromString<T>(s.data(), s.size(), result);
}

template <class T>
inline bool TryFromString(const std::string& s, T& result) {
    return TryFromString<T>(s.data(), s.size(), result);
}

template <class T>
inline bool TryFromString(const TWtringBuf& s, T& result) {
    return TryFromString<T>(s.data(), s.size(), result);
}

template <class T>
inline bool TryFromString(const TUtf16String& s, T& result) {
    return TryFromString<T>(s.data(), s.size(), result);
}

template <class T, class TChar>
inline TMaybe<T> TryFromString(TBasicStringBuf<TChar> s) {
    TMaybe<T> result{NMaybe::TInPlace{}};
    if (!TryFromString<T>(s, *result)) {
        result.Clear();
    }

    return result;
}

template <class T, class TChar>
inline TMaybe<T> TryFromString(const TChar* data) {
    return TryFromString<T>(TBasicStringBuf<TChar>(data));
}

template <class T>
inline TMaybe<T> TryFromString(const TString& s) {
    return TryFromString<T>(TStringBuf(s));
}

template <class T>
inline TMaybe<T> TryFromString(const std::string& s) {
    return TryFromString<T>(TStringBuf(s));
}

template <class T>
inline TMaybe<T> TryFromString(const TUtf16String& s) {
    return TryFromString<T>(TWtringBuf(s));
}

template <class T, class TStringType>
inline bool TryFromStringWithDefault(const TStringType& s, T& result, const T& def) {
    return TryFromString<T>(s.data(), s.size(), result, def);
}

template <class T>
inline bool TryFromStringWithDefault(const char* s, T& result, const T& def) {
    return TryFromStringWithDefault<T>(TStringBuf(s), result, def);
}

template <class T, class TStringType>
inline bool TryFromStringWithDefault(const TStringType& s, T& result) {
    return TryFromStringWithDefault<T>(s, result, T());
}

// FromString methods with default value if data is invalid
template <class T, class TChar>
inline T FromString(const TChar* data, const size_t len, const T& def) {
    T result;
    TryFromString<T>(data, len, result, def);
    return result;
}

template <class T, class TStringType>
inline T FromStringWithDefault(const TStringType& s, const T& def) {
    return FromString<T>(s.data(), s.size(), def);
}

template <class T>
inline T FromStringWithDefault(const char* s, const T& def) {
    return FromStringWithDefault<T>(TStringBuf(s), def);
}

template <class T, class TStringType>
inline T FromStringWithDefault(const TStringType& s) {
    return FromStringWithDefault<T>(s, T());
}

double StrToD(const char* b, char** se);
double StrToD(const char* b, const char* e, char** se);

template <int base, class T>
size_t IntToString(T t, char* buf, size_t len);

template <int base, class T>
inline TString IntToString(T t) {
    static_assert(std::is_arithmetic<std::remove_cv_t<T>>::value, "expect std::is_arithmetic<std::remove_cv_t<T>>::value");

    char buf[256];

    return TString(buf, IntToString<base>(t, buf, sizeof(buf)));
}

template <int base, class TInt, class TChar>
bool TryIntFromString(const TChar* data, size_t len, TInt& result);

template <int base, class TInt, class TStringType>
inline bool TryIntFromString(const TStringType& s, TInt& result) {
    return TryIntFromString<base>(s.data(), s.size(), result);
}

template <class TInt, int base, class TChar>
TInt IntFromString(const TChar* str, size_t len);

template <class TInt, int base, class TChar>
inline TInt IntFromString(const TChar* str) {
    return IntFromString<TInt, base>(str, std::char_traits<TChar>::length(str));
}

template <class TInt, int base, class TStringType>
inline TInt IntFromString(const TStringType& str) {
    return IntFromString<TInt, base>(str.data(), str.size());
}

static inline TString ToString(const TStringBuf str) {
    return TString(str);
}

static inline TUtf16String ToWtring(const TWtringBuf wtr) {
    return TUtf16String(wtr);
}

static inline TUtf32String ToUtf32String(const TUtf32StringBuf wtr) {
    return TUtf32String(wtr);
}