File: print_half.cpp

package info (click to toggle)
boost1.90 1.90.0-5
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 593,168 kB
  • sloc: cpp: 4,190,642; xml: 196,648; python: 34,618; ansic: 23,145; asm: 5,468; sh: 3,776; makefile: 1,162; perl: 1,020; sql: 728; ruby: 676; yacc: 478; java: 77; lisp: 24; csh: 6
file content (119 lines) | stat: -rw-r--r-- 3,512 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
// Copyright 2018-2024 Emil Dotchevski and Reverge Studios, Inc.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

// This program is an adaptation of the following Boost Outcome example:
// https://github.com/ned14/outcome/blob/master/doc/src/snippets/using_result.cpp

#include <boost/leaf.hpp>
#include <algorithm>
#include <ctype.h>
#include <string>
#include <iostream>

namespace leaf = boost::leaf;

enum class ConversionErrc
{
    EmptyString = 1,
    IllegalChar,
    TooLong
};

leaf::result<int> convert(const std::string& str) noexcept
{
    if (str.empty())
        return leaf::new_error(ConversionErrc::EmptyString);

    if (!std::all_of(str.begin(), str.end(), ::isdigit))
        return leaf::new_error(ConversionErrc::IllegalChar);

    if (str.length() > 9)
        return leaf::new_error(ConversionErrc::TooLong);

    return atoi(str.c_str());
}

// Do not static_store BigInt to actually work -- it's a stub.
struct BigInt
{
    static leaf::result<BigInt> fromString(const std::string& s) { return BigInt{s}; }
    explicit BigInt(const std::string&) { }
    BigInt half() const { return BigInt{""}; }
    friend std::ostream& operator<<(std::ostream& o, const BigInt&) { return o << "big int half"; }
};

// This function handles ConversionErrc::TooLong errors, forwards any other
// error to the caller.
leaf::result<void> print_half(const std::string& text)
{
    return leaf::try_handle_some(
        [&]() -> leaf::result<void>
        {
            BOOST_LEAF_AUTO(r,convert(text));
            std::cout << r / 2 << std::endl;
            return { };
        },
        [&]( leaf::match<ConversionErrc, ConversionErrc::TooLong> ) -> leaf::result<void>
        {
            BOOST_LEAF_AUTO(i, BigInt::fromString(text));
            std::cout << i.half() << std::endl;
            return { };
        } );
}

int main( int argc, char const * argv[] )
{
    return leaf::try_handle_all(
        [&]() -> leaf::result<int>
        {
            BOOST_LEAF_CHECK( print_half(argc<2 ? "" : argv[1]) );
            std::cout << "ok" << std::endl;
            return 0;
        },

        []( leaf::match<ConversionErrc, ConversionErrc::EmptyString> )
        {
            std::cerr << "Empty string!" << std::endl;
            return 1;
        },

        []( leaf::match<ConversionErrc, ConversionErrc::IllegalChar> )
        {
            std::cerr << "Illegal char!" << std::endl;
            return 2;
        },

        []( leaf::error_info const & unmatched )
        {
            // This will never execute in this program, but it would detect
            // logic errors where an unknown error reaches main. In this case,
            // we print diagnostic information.
            std::cerr <<
                "Unknown failure detected" << std::endl <<
                "Cryptic diagnostic information follows" << std::endl <<
                unmatched;
            return 3;
        } );
}

////////////////////////////////////////

#ifdef BOOST_LEAF_NO_EXCEPTIONS

namespace boost
{
    [[noreturn]] void throw_exception( std::exception const & e )
    {
        std::cerr << "Terminating due to a C++ exception under BOOST_LEAF_NO_EXCEPTIONS: " << e.what();
        std::terminate();
    }

    struct source_location;
    [[noreturn]] void throw_exception( std::exception const & e, boost::source_location const & )
    {
        throw_exception(e);
    }
}

#endif