| 740 | } |
| 741 | |
| 742 | string format_string( const string& frmt, const variant_object& args, bool minimize ) |
| 743 | { |
| 744 | std::string result; |
| 745 | const string& format = ( minimize && frmt.size() > minimize_max_size ) ? |
| 746 | frmt.substr( 0, minimize_max_size ) + "..." : frmt; |
| 747 | |
| 748 | const auto arg_num = (args.size() == 0) ? 1 : args.size(); |
| 749 | const auto max_format_size = std::max(minimize_max_size, format.size()); |
| 750 | // limit each arg size when minimize is set |
| 751 | const auto minimize_sub_max_size = minimize ? ( max_format_size - format.size() ) / arg_num : minimize_max_size; |
| 752 | // reserve space for each argument replaced by ... |
| 753 | result.reserve( max_format_size + 3 * args.size()); |
| 754 | size_t prev = 0; |
| 755 | size_t next = format.find( '$' ); |
| 756 | while( prev != string::npos && prev < format.size() ) { |
| 757 | if( next != string::npos ) { |
| 758 | clean_append( result, format, prev, next - prev ); |
| 759 | } else { |
| 760 | clean_append( result, format, prev ); |
| 761 | } |
| 762 | |
| 763 | // if we got to the end, return it. |
| 764 | if( next == string::npos ) { |
| 765 | return result; |
| 766 | } else if( minimize && result.size() > minimize_max_size ) { |
| 767 | result += "..."; |
| 768 | return result; |
| 769 | } |
| 770 | |
| 771 | // if we are not at the end, then update the start |
| 772 | prev = next + 1; |
| 773 | |
| 774 | if( format[prev] == '{' ) { |
| 775 | // if the next char is a open, then find close |
| 776 | next = format.find( '}', prev ); |
| 777 | // if we found close... |
| 778 | if( next != string::npos ) { |
| 779 | // the key is between prev and next |
| 780 | string key = format.substr( prev + 1, (next - prev - 1) ); |
| 781 | |
| 782 | auto val = args.find( key ); |
| 783 | bool replaced = true; |
| 784 | if( val != args.end() ) { |
| 785 | if( val->value().is_object() || val->value().is_array() ) { |
| 786 | if( minimize && (result.size() >= minimize_max_size)) { |
| 787 | replaced = false; |
| 788 | } else { |
| 789 | const auto max_length = minimize ? minimize_sub_max_size : std::numeric_limits<uint64_t>::max(); |
| 790 | try { |
| 791 | // clean_append not needed as to_string is valid utf8 |
| 792 | result += json::to_string( val->value(), fc::time_point::maximum(), |
| 793 | json::output_formatting::stringify_large_ints_and_doubles, max_length ); |
| 794 | } catch (...) { |
| 795 | replaced = false; |
| 796 | } |
| 797 | } |
| 798 | } else if( val->value().is_blob() ) { |
| 799 | if( minimize && val->value().get_blob().data.size() > minimize_sub_max_size ) { |
no test coverage detected