int NetworkingObjectBase::TruncateValueStrings()

in src/modules/networking/src/lib/Networking.cpp [814:886]


int NetworkingObjectBase::TruncateValueStrings(std::vector<std::pair<std::string, std::string>>& fieldValueVector)
{
    // If m_maxPayloadSizeBytes is zero or a negative number, or too small we do not truncate
    if ((m_maxPayloadSizeBytes <= 0) || (m_maxPayloadSizeBytes <= g_templateWithDotsSize))
    {
        return MMI_OK;
    }

    unsigned int maxValueSize = 0;
    unsigned int totalValueSize = 0;
    maxValueSize =  (m_maxPayloadSizeBytes > g_templateSize) ? m_maxPayloadSizeBytes - g_templateSize : 0;
    std::vector<std::string> fields;

    for (size_t i = 0; i < fieldValueVector.size(); i++)
    {
        fields.push_back(fieldValueVector[i].first);
        totalValueSize += fieldValueVector[i].second.length();
    }

    if (totalValueSize > maxValueSize)
    {
        sort(fieldValueVector.begin(), fieldValueVector.end(), [](std::pair<std::string, std::string>& a, std::pair<std::string, std::string>& b)
        {
            return (a.second.length() < b.second.length()) || ((a.second.length() == b.second.length()) && a.first < b.first);
        });

        for (size_t i = 0; i < fieldValueVector.size(); i++)
        {
            std::string keyString = fieldValueVector[i].first;
            std::string valueString = fieldValueVector[i].second;
            if (totalValueSize > maxValueSize)
            {
                unsigned int cutPerField = 0;
                // Number of fields to truncate
                unsigned int numFieldsToCut = fieldValueVector.size() - i;
                // Size to truncate for each field (value string)
                cutPerField = ((totalValueSize - maxValueSize) / numFieldsToCut) + (((totalValueSize - maxValueSize) % numFieldsToCut) ? 1 : 0);
                unsigned int lengthBeforeCut = valueString.length();
                if (valueString.length() > g_twoDotsSize)
                {
                    if (valueString.length() < cutPerField + g_twoDotsSize)
                    {
                        // If we truncate a string, the mininum length is two
                        valueString = g_twoDots;
                    }
                    else
                    {
                        valueString = valueString.substr(0, valueString.length() - g_twoDotsSize - cutPerField) + g_twoDots;
                    }
                }
                // If value string size is less than two bytes, keep it as is
                unsigned int lengthAfterCut = valueString.length();
                totalValueSize -= ((lengthBeforeCut > lengthAfterCut) ? (lengthBeforeCut - lengthAfterCut) : 0);

                fieldValueVector[i].second = valueString;
            }
        }

        // Sort vector back to orginial order
        std::unordered_map<std::string, int> position;
        for (int i = 0; i < (int)fields.size(); i++)
        {
            position[fields[i]] = i;
        }

        sort(fieldValueVector.begin(), fieldValueVector.end(), [&position](std::pair<std::string, std::string>& a, std::pair<std::string, std::string>& b)
        {
            return (position[a.first] < position[b.first]) || ((position[a.first] == position[b.first]) && (a.second < b.second));
        });
    }

    return (totalValueSize + g_templateSize <= m_maxPayloadSizeBytes) ? MMI_OK : ENODATA;
}