Parse a memory size from a string. * * The string may indicate the units of the memory (e.g., "230k", "500 MB"), * using the prefixes "k", "m", or "g" in either lower or upper-case, * optionally followed by a "b" or "B". The string may alternatively specify * memory as a fraction of the usable RAM (e.g., "25%"). Spaces before the * number, between the number and the units, or after the units
| 1749 | * @since 3.10 |
| 1750 | */ |
| 1751 | CPLErr CPLParseMemorySize(const char *pszValue, GIntBig *pnValue, |
| 1752 | bool *pbUnitSpecified) |
| 1753 | { |
| 1754 | const char *start = pszValue; |
| 1755 | char *end = nullptr; |
| 1756 | |
| 1757 | // trim leading whitespace |
| 1758 | while (*start == ' ') |
| 1759 | { |
| 1760 | start++; |
| 1761 | } |
| 1762 | |
| 1763 | auto len = CPLStrnlen(start, 100); |
| 1764 | double value = CPLStrtodM(start, &end); |
| 1765 | const char *unit = nullptr; |
| 1766 | bool unitIsNotPercent = false; |
| 1767 | |
| 1768 | if (end == start) |
| 1769 | { |
| 1770 | CPLError(CE_Failure, CPLE_IllegalArg, "Received non-numeric value: %s", |
| 1771 | pszValue); |
| 1772 | return CE_Failure; |
| 1773 | } |
| 1774 | |
| 1775 | if (value < 0 || !std::isfinite(value)) |
| 1776 | { |
| 1777 | CPLError(CE_Failure, CPLE_IllegalArg, |
| 1778 | "Memory size must be a positive number or zero."); |
| 1779 | return CE_Failure; |
| 1780 | } |
| 1781 | |
| 1782 | for (const char *c = end; c < start + len; c++) |
| 1783 | { |
| 1784 | if (unit == nullptr) |
| 1785 | { |
| 1786 | // check various suffixes and convert number into bytes |
| 1787 | if (*c == '%') |
| 1788 | { |
| 1789 | if (value < 0 || value > 100) |
| 1790 | { |
| 1791 | CPLError(CE_Failure, CPLE_IllegalArg, |
| 1792 | "Memory percentage must be between 0 and 100."); |
| 1793 | return CE_Failure; |
| 1794 | } |
| 1795 | auto bytes = CPLGetUsablePhysicalRAM(); |
| 1796 | if (bytes == 0) |
| 1797 | { |
| 1798 | CPLError(CE_Failure, CPLE_NotSupported, |
| 1799 | "Cannot determine usable physical RAM"); |
| 1800 | return CE_Failure; |
| 1801 | } |
| 1802 | value *= static_cast<double>(bytes / 100); |
| 1803 | unit = c; |
| 1804 | } |
| 1805 | else |
| 1806 | { |
| 1807 | switch (*c) |
| 1808 | { |