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


#include <print>
#include <string>
#include <charconv>
#include <cctype>

void traceStringData(const std::string& s)
{
  // print all character of the allocated memory:
  std::print("["); 
  for (unsigned i = 0; i < s.capacity(); ++i) {
    char c = s.data()[i];
    if (c == '\0') c = 'T';         // use 'T' for the null terminator '\0'
    if (!std::isprint(c)) c = '?';  // use '?' for non-printable characters
    std::print("{}", c);            // otherwise print the character as it is
  }
  // show which characters are part of the value:
  std::println("]\n\"{}\"\n", std::string(s.size(), '^'));
}

int main()
{
  // simulate string with 25 characters, null terminator, and extra memory:
  std::string s = "-------------------------T?????";
  traceStringData(s);      //  -------------------------T?????

  // resize string to have 10 characters:
  s.resize(10);
  traceStringData(s);      //  ----------T--------------T?????

  // patch and resize string
  s.resize_and_overwrite(20,                                    // requested maxsize
                         [sz = s.size()](char* buf, std::size_t n) {
                           std::to_chars(buf+2, buf+sz-2, n);   // store "20"
                           return 13;                           // return new size
                         });
  traceStringData(s);      //  --20------T--T-----------T?????
}

