Completed implementing standard formatting.

This commit is contained in:
Bil Bas (Spooner) 2015-02-01 18:42:36 +00:00
parent 7a41f8c604
commit 6306254d37
2 changed files with 135 additions and 40 deletions

View File

@ -35,7 +35,6 @@
#include "ucaps.h" #include "ucaps.h"
#include "color.h" #include "color.h"
#include "variant.h" #include "variant.h"
#include <stdio.h>
#define MAX_DIGITS 6 #define MAX_DIGITS 6
#define UPPERCASE(m_c) (((m_c)>='a' && (m_c)<='z')?((m_c)-('a'-'A')):(m_c)) #define UPPERCASE(m_c) (((m_c)>='a' && (m_c)<='z')?((m_c)-('a'-'A')):(m_c))
#define LOWERCASE(m_c) (((m_c)>='A' && (m_c)<='Z')?((m_c)+('a'-'A')):(m_c)) #define LOWERCASE(m_c) (((m_c)>='A' && (m_c)<='Z')?((m_c)+('a'-'A')):(m_c))
@ -983,7 +982,7 @@ String String::num(double p_num,int p_decimals) {
} }
String String::num_int64(int64_t p_num) { String String::num_int64(int64_t p_num, int base, bool capitalize_hex) {
bool sign=p_num<0; bool sign=p_num<0;
int64_t num=ABS(p_num); int64_t num=ABS(p_num);
@ -992,7 +991,7 @@ String String::num_int64(int64_t p_num) {
int chars=0; int chars=0;
do { do {
n/=10; n/=base;
chars++; chars++;
} while(n); } while(n);
@ -1004,8 +1003,15 @@ String String::num_int64(int64_t p_num) {
c[chars]=0; c[chars]=0;
n=num; n=num;
do { do {
c[--chars]='0'+(n%10); int mod = n%base;
n/=10; if (mod >= 10) {
char a = (capitalize_hex ? 'A' : 'a');
c[--chars]=a+(mod - 10);
} else {
c[--chars]='0'+mod;
}
n/=base;
} while(n); } while(n);
if (sign) if (sign)
@ -3520,41 +3526,84 @@ String rtoss(double p_val) {
return String::num_scientific(p_val); return String::num_scientific(p_val);
} }
// Right-pad with a character.
String String::rpad(int min_length, const String& character) const {
String s = *this;
int padding = min_length - s.length();
if (padding > 0) {
for (int i = 0; i < padding; i++) s = s + character;
}
return s;
}
// Left-pad with a character.
String String::lpad(int min_length, const String& character) const {
String s = *this;
int padding = min_length - s.length();
if (padding > 0) {
for (int i = 0; i < padding; i++) s = character + s;
}
return s;
}
// sprintf is implemented in GDScript via: // sprintf is implemented in GDScript via:
// "fish %s pie" % "frog" // "fish %s pie" % "frog"
// "fish %s %d pie" % ["frog", 12] // "fish %s %d pie" % ["frog", 12]
const int FORMAT_BUFFER_SIZE = 1024;
const int OUTPUT_BUFFER_SIZE = 1024 * 100;
String String::sprintf(const Array& values) const { String String::sprintf(const Array& values) const {
String formatted; String formatted;
CharType* self = (CharType*)c_str(); CharType* self = (CharType*)c_str();
bool in_format = false; bool in_format = false;
int value_index = 0; int value_index = 0;
char format_format[FORMAT_BUFFER_SIZE] = "%d"; int min_chars;
int num_decimals;
bool in_decimals;
bool pad_with_zeroes;
bool left_justified;
bool show_sign;
for (; *self; self++) { for (; *self; self++) {
const CharType c = *self; const CharType c = *self;
if (in_format) { // We have % - lets see what else we get. if (in_format) { // We have % - lets see what else we get.
switch (c) { switch (c) {
case '%': // Manage %% as % case '%': { // Replace %% with %
formatted += chr(c); formatted += chr(c);
in_format = false; in_format = false;
break; break;
}
case 'd': // Integer (signed) case 'd': // Integer (signed)
case 'o': // Octal case 'o': // Octal
case 'x': // Hexadecimal (lowercase) case 'x': // Hexadecimal (lowercase)
case 'X': // Hexadecimal (uppercase) case 'X': { // Hexadecimal (uppercase)
if (values[value_index].is_num()) { if (values[value_index].is_num()) {
char buffer[OUTPUT_BUFFER_SIZE]; int64_t value = values[value_index];
int value = values[value_index]; int base;
format_format[1] = c; bool capitalize = false;
format_format[2] = 0; switch (c) {
::sprintf(buffer, format_format, value); case 'd': base = 10; break;
case 'o': base = 8; break;
formatted += String(buffer); case 'x': base = 16; break;
case 'X': base = 16; capitalize = true; break;
}
// Get basic number.
String str = String::num_int64(value, base, capitalize);
// Sign.
if (show_sign && value >= 0) {
str = str.insert(0, "+");
}
// Padding.
String pad_char = pad_with_zeroes ? String("0") : String(" ");
if (left_justified) {
str = str.rpad(min_chars, pad_char);
} else {
str = str.lpad(min_chars, pad_char);
}
formatted += str;
++value_index; ++value_index;
in_format = false; in_format = false;
} else { } else {
@ -3562,14 +3611,28 @@ String String::sprintf(const Array& values) const {
} }
break; break;
}
case 'f': // Float case 'f': { // Float
if (values[value_index].is_num()) { if (values[value_index].is_num()) {
char buffer[OUTPUT_BUFFER_SIZE];
double value = values[value_index]; double value = values[value_index];
::sprintf(buffer, "%f", value); String str = String::num(value, num_decimals);
formatted += String(buffer); // Pad decimals out.
str = str.pad_decimals(num_decimals);
// Show sign
if (show_sign && value >= 0) {
str = str.insert(0, "+");
}
// Padding
if (left_justified) {
str = str.rpad(min_chars);
} else {
str = str.lpad(min_chars);
}
formatted += str;
++value_index; ++value_index;
in_format = false; in_format = false;
} else { } else {
@ -3577,26 +3640,49 @@ String String::sprintf(const Array& values) const {
} }
break; break;
}
case 's': { // String
String str = values[value_index];
// Padding.
if (left_justified) {
str = str.rpad(min_chars);
} else {
str = str.lpad(min_chars);
}
case 's': // String formatted += str;
String value = values[value_index];
formatted += value;
++value_index; ++value_index;
in_format = false; in_format = false;
break; break;
}
// case '-': // Left justify case '-': { // Left justify
// break; left_justified = true;
break;
// case '+': // Show + if positive. }
// break; case '+': { // Show + if positive.
show_sign = true;
// case '0': case '1': case '2': case '3': case '4': break;
// case '5': case '6': case '7': case '8': case '9': }
// break; case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': {
// case '.': // Float separtor. int n = c - '0';
// break; if (in_decimals) {
num_decimals *= 10;
num_decimals += n;
} else {
if (c == '0' && min_chars == 0) {
pad_with_zeroes = true;
} else {
min_chars *= 10;
min_chars += n;
}
}
break;
}
case '.': // Float separtor.
in_decimals = true;
num_decimals = 0; // We want to add the value manually.
break;
// case '*': // Dyanmic width, based on value. // case '*': // Dyanmic width, based on value.
// break; // break;
@ -3608,6 +3694,13 @@ String String::sprintf(const Array& values) const {
switch (c) { switch (c) {
case '%': case '%':
in_format = true; in_format = true;
// Back to defaults:
min_chars = 0;
num_decimals = 6;
pad_with_zeroes = false;
left_justified = false;
show_sign = false;
in_decimals = false;
break; break;
default: default:
formatted += chr(c); formatted += chr(c);

View File

@ -128,11 +128,13 @@ public:
String insert(int p_at_pos,String p_string) const; String insert(int p_at_pos,String p_string) const;
String pad_decimals(int p_digits) const; String pad_decimals(int p_digits) const;
String pad_zeros(int p_digits) const; String pad_zeros(int p_digits) const;
String lpad(int min_length,const String& character=" ") const;
String rpad(int min_length,const String& character=" ") const;
String sprintf(const Array& values) const; String sprintf(const Array& values) const;
static String num(double p_num,int p_decimals=-1); static String num(double p_num,int p_decimals=-1);
static String num_scientific(double p_num); static String num_scientific(double p_num);
static String num_real(double p_num); static String num_real(double p_num);
static String num_int64(int64_t p_num); static String num_int64(int64_t p_num,int base=10,bool capitalize_hex=false);
static String chr(CharType p_char); static String chr(CharType p_char);
static String md5(const uint8_t *p_md5); static String md5(const uint8_t *p_md5);
bool is_numeric() const; bool is_numeric() const;