//********************************************************
// The following code example is taken from the book
//  C++23 - The Complete Guide
//  by Nicolai M. Josuttis (www.josuttis.com)
//  http://www.cppstd23.com
//
// The code is licensed under a
//  Creative Commons Attribution 4.0 International License
//  http://creativecommons.org/licenses/by/4.0/
//********************************************************


#include <iostream>
#include <string>
#include <sstream>
#include <optional>

// return non-empty string read from a stream or "no value"
std::optional<std::string> readLine(std::istream& is)
{
  std::cout << "readLine()";
  std::string row;
  if (std::getline(is, row) && !row.empty()) {
    std::cout <<  " => \"" << row << "\"\n";
    return row;
  }
  std::cout <<  " => <noline>\n";
  return std::nullopt;   // no non-empty line read
}

// return string converted into int or "no value"
std::optional<int> asInt(const std::string& s)
{
  try {
    return std::stoi(s);
  }
  catch (...) {
    return {};
  }
}

void process(std::istream& strm)
{
  auto square = [] (int val) { return 1L * val * val; };

  while (strm) {
    // read next line, convert to int and square as long:
    std::optional opt = readLine(strm).and_then(asInt).transform(square);
    if (opt) {
      std::cout << *opt << "\n\n";   
    }
    else {
      std::cout << "<novalue>\n\n";  
    }
  }
}

int main()
{
  // simulate input stream:
  static std::stringstream sStrm{"42\ndata\n"};

  process(sStrm);
}

