// Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Compared with std::stringstream, there are primary purpose of // string::Printf: // // 1. Type-safe printing, with why and how explained in // http://www.drdobbs.com/stringprintf-a-typesafe-printf-family-fo/184401999. // Implementation includes // // https://github.com/c42f/tinyformat // boost::format // std::stringstream // // std::stringstream is not convenient enough in many cases. For example: // // std::cout << std::setprecision(2) << std::fixed << 1.23456 << "\n"; // // boost::format is the most convenient one. We can have // // std::cout << format("%2% %1%") % 36 % 77; // // or // // format fmter("%2% %1%"); // fmter % 36; fmter % 77; // std::cout << fmter.c_str(); // // But the overloading of % might be overkilling and it would be // more efficient if it can write to std::cout directly. // // tinyformat has an interface compatible with the C-printf style, // and it can writes to a stream or returns a std::string: // // std::cout << tfm::printf( // "%s, %s %d, %.2d:%.2d\n", // weekday, month, day, hour, min); // // or // // tfm::format(std::cout, // "%s, %s %d, %.2d:%.2d\n", // weekday, month, day, hour, min); // // 2. High-performance -- most printed strings are not too long and // doens't need dynamic memory allocation. Many StringPrintf // implementations doesn't enforce type-safe, but are // high-performance, including // // https://developers.google.com/optimization/reference/base/stringprintf/ // https://github.com/adobe/chromium/blob/master/base/stringprintf.h // https://github.com/google/protobuf/blob/master/src/google/protobuf/stubs/stringprintf.h // // According to // https://github.com/c42f/tinyformat#compile-time-and-code-bloat, // boost::format runs too slow and results in large executable binary // files. So here we port tinyformat. #pragma once #include #include #include #include #include "tinyformat/tinyformat.h" // https://github.com/c42f/tinyformat namespace paddle { namespace string { template void Fprintf(std::ostream& out, const char* fmt, const Args&... args) { tinyformat::vformat(out, fmt, tinyformat::makeFormatList(args...)); } template std::string Sprintf(const Args&... args) { std::ostringstream oss; Fprintf(oss, "%s", args...); return oss.str(); } template std::string Sprintf(const char* fmt, const Args&... args) { std::ostringstream oss; Fprintf(oss, fmt, args...); return oss.str(); } template void Printf(const char* fmt, const Args&... args) { Fprintf(std::cout, fmt, args...); } template std::string HumanReadableSize(T size) { size_t i = 0; double f_size = static_cast(size); double orig = f_size; const std::vector units( {"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"}); while (f_size > 1024) { f_size /= 1024; i++; } if (i >= units.size()) { return Sprintf("%fB", orig); } return Sprintf("%f%s", f_size, units[i]); } } // namespace string } // namespace paddle