reapack

Package manager for REAPER
Log | Files | Refs | Submodules | README | LICENSE

string.cpp (2651B)


      1 /* ReaPack: Package manager for REAPER
      2  * Copyright (C) 2015-2025  Christian Fillion
      3  *
      4  * This program is free software: you can redistribute it and/or modify
      5  * it under the terms of the GNU Lesser General Public License as published by
      6  * the Free Software Foundation, either version 3 of the License, or
      7  * (at your option) any later version.
      8  *
      9  * This program is distributed in the hope that it will be useful,
     10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12  * GNU Lesser General Public License for more details.
     13  *
     14  * You should have received a copy of the GNU Lesser General Public License
     15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
     16  */
     17 
     18 #include "string.hpp"
     19 
     20 #include <boost/algorithm/string/replace.hpp>
     21 #include <boost/algorithm/string/trim.hpp>
     22 #include <cstdarg>
     23 #include <regex>
     24 #include <sstream>
     25 
     26 std::string String::format(const char *fmt, ...)
     27 {
     28   va_list args;
     29 
     30   va_start(args, fmt);
     31   const int size = vsnprintf(nullptr, 0, fmt, args);
     32   va_end(args);
     33 
     34   std::string buf(size, 0);
     35 
     36   va_start(args, fmt);
     37   vsnprintf(&buf[0], size + 1, fmt, args);
     38   va_end(args);
     39 
     40   return buf;
     41 }
     42 
     43 std::string String::indent(const std::string &text)
     44 {
     45   std::string output;
     46   std::istringstream input(text);
     47   std::string line;
     48   bool first = true;
     49 
     50   while(getline(input, line, '\n')) {
     51     if(first)
     52       first = false;
     53     else
     54       output += "\r\n";
     55 
     56     boost::algorithm::trim(line);
     57 
     58     if(line.empty())
     59       continue;
     60 
     61     output += "\x20\x20";
     62     output += line;
     63   }
     64 
     65   return output;
     66 }
     67 
     68 std::string String::stripRtf(const std::string &rtf)
     69 {
     70   static const std::regex rtfRules(
     71     // passthrough for later replacement to \n
     72     R"((\\line |\\par\}))" "|"
     73     R"(\\line(\n)\s*)" "|"
     74 
     75     // preserve literal braces
     76     R"(\\([\{\}]))" "|"
     77 
     78     // hidden groups (strip contents)
     79     R"(\{\\(?:f\d+|fonttbl|colortbl)[^\{\}]+\})" "|"
     80 
     81     // formatting tags and groups (keep contents)
     82     R"(\\\w+\s?|\{|\})" "|"
     83 
     84     // newlines and indentation
     85     R"(\s*\n\s*)"
     86   );
     87 
     88   std::string text = std::regex_replace(rtf, rtfRules, "$1$2$3");
     89   boost::algorithm::replace_all(text, "\\line ", "\n");
     90   boost::algorithm::replace_all(text, "\\par}", "\n\n");
     91   boost::algorithm::trim(text);
     92 
     93   return text;
     94 }
     95 
     96 void String::ImplDetail::imbueStream(std::ostream &stream)
     97 {
     98   class NumPunct : public std::numpunct<char>
     99   {
    100   protected:
    101     char do_thousands_sep() const override { return ','; }
    102     std::string do_grouping() const override { return "\3"; }
    103   };
    104 
    105   stream.imbue(std::locale(std::locale::classic(), new NumPunct));
    106 }