Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
mruby
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Libraries
mruby
Commits
e9877bc7
Unverified
Commit
e9877bc7
authored
Apr 14, 2020
by
Yukihiro "Matz" Matsumoto
Committed by
GitHub
Apr 14, 2020
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #4970 from dearblue/nostdio-sprintf
Support `MRB_DISABLE_STDIO` for mruby-sprintf; ref #4954
parents
ea632ab8
191ccbf6
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
157 additions
and
46 deletions
+157
-46
include/mruby/numeric.h
include/mruby/numeric.h
+1
-0
mrbgems/mruby-sprintf/src/sprintf.c
mrbgems/mruby-sprintf/src/sprintf.c
+53
-25
mrbgems/mruby-sprintf/test/sprintf.rb
mrbgems/mruby-sprintf/test/sprintf.rb
+5
-0
src/fmt_fp.c
src/fmt_fp.c
+98
-21
No files found.
include/mruby/numeric.h
View file @
e9877bc7
...
...
@@ -37,6 +37,7 @@ MRB_API mrb_value mrb_fixnum_to_str(mrb_state *mrb, mrb_value x, mrb_int base);
/* ArgumentError if format string doesn't match /%(\.[0-9]+)?[aAeEfFgG]/ */
#ifndef MRB_WITHOUT_FLOAT
MRB_API
mrb_value
mrb_float_to_str
(
mrb_state
*
mrb
,
mrb_value
x
,
const
char
*
fmt
);
MRB_API
int
mrb_float_to_cstr
(
mrb_state
*
mrb
,
char
*
buf
,
size_t
len
,
const
char
*
fmt
,
mrb_float
f
);
MRB_API
mrb_float
mrb_to_flo
(
mrb_state
*
mrb
,
mrb_value
x
);
MRB_API
mrb_value
mrb_int_value
(
mrb_state
*
mrb
,
mrb_float
f
);
#endif
...
...
mrbgems/mruby-sprintf/src/sprintf.c
View file @
e9877bc7
...
...
@@ -5,11 +5,6 @@
*/
#include <mruby.h>
#ifdef MRB_DISABLE_STDIO
# error sprintf conflicts 'MRB_DISABLE_STDIO' configuration in your 'build_config.rb'
#endif
#include <limits.h>
#include <string.h>
#include <mruby/string.h>
...
...
@@ -521,6 +516,50 @@ mrb_f_sprintf(mrb_state *mrb, mrb_value obj)
}
}
static
int
mrb_int2str
(
char
*
buf
,
size_t
len
,
mrb_int
n
)
{
#ifdef MRB_DISABLE_STDIO
char
*
bufend
=
buf
+
len
;
char
*
p
=
bufend
-
1
;
if
(
len
<
1
)
return
-
1
;
*
p
--
=
'\0'
;
len
--
;
if
(
n
<
0
)
{
if
(
len
<
1
)
return
-
1
;
*
p
--
=
'-'
;
len
--
;
n
=
-
n
;
}
if
(
n
>
0
)
{
for
(;
n
>
0
;
len
--
,
n
/=
10
)
{
if
(
len
<
1
)
return
-
1
;
*
p
--
=
'0'
+
(
n
%
10
);
}
p
++
;
}
else
if
(
len
>
0
)
{
*
p
=
'0'
;
len
--
;
}
else
{
return
-
1
;
}
memmove
(
buf
,
p
,
bufend
-
p
);
return
bufend
-
p
-
1
;
#else
return
snprintf
(
buf
,
len
,
"%"
MRB_PRId
,
n
);
#endif
/* MRB_DISABLE_STDIO */
}
mrb_value
mrb_str_format
(
mrb_state
*
mrb
,
mrb_int
argc
,
const
mrb_value
*
argv
,
mrb_value
fmt
)
{
...
...
@@ -869,7 +908,7 @@ retry:
width
--
;
}
mrb_assert
(
base
==
10
);
snprintf
(
nbuf
,
sizeof
(
nbuf
),
"%"
MRB_PRId
,
v
);
mrb_int2str
(
nbuf
,
sizeof
(
nbuf
)
,
v
);
s
=
nbuf
;
if
(
v
<
0
)
s
++
;
/* skip minus sign */
}
...
...
@@ -877,24 +916,12 @@ retry:
s
=
nbuf
;
if
(
v
<
0
)
{
dots
=
1
;
}
switch
(
base
)
{
case
2
:
if
(
v
<
0
)
{
val
=
mrb_fix2binstr
(
mrb
,
mrb_fixnum_value
(
v
),
base
);
}
else
{
val
=
mrb_fixnum_to_str
(
mrb
,
mrb_fixnum_value
(
v
),
base
);
}
strncpy
(
++
s
,
RSTRING_PTR
(
val
),
sizeof
(
nbuf
)
-
1
);
break
;
case
8
:
snprintf
(
++
s
,
sizeof
(
nbuf
)
-
1
,
"%"
MRB_PRIo
,
v
);
break
;
case
16
:
snprintf
(
++
s
,
sizeof
(
nbuf
)
-
1
,
"%"
MRB_PRIx
,
v
);
break
;
}
if
(
v
<
0
)
{
char
d
;
...
...
@@ -1071,7 +1098,7 @@ retry:
need
+=
20
;
CHECK
(
need
);
n
=
snprintf
(
&
buf
[
blen
],
need
,
fbuf
,
fval
);
n
=
mrb_float_to_cstr
(
mrb
,
&
buf
[
blen
],
need
,
fbuf
,
fval
);
if
(
n
<
0
||
n
>=
need
)
{
mrb_raise
(
mrb
,
E_RUNTIME_ERROR
,
"formatting error"
);
}
...
...
@@ -1113,12 +1140,13 @@ fmt_setup(char *buf, size_t size, int c, int flags, mrb_int width, mrb_int prec)
if
(
flags
&
FSPACE
)
*
buf
++
=
' '
;
if
(
flags
&
FWIDTH
)
{
n
=
snprintf
(
buf
,
end
-
buf
,
"%d"
,
(
int
)
width
);
n
=
mrb_int2str
(
buf
,
end
-
buf
,
width
);
buf
+=
n
;
}
if
(
flags
&
FPREC
)
{
n
=
snprintf
(
buf
,
end
-
buf
,
".%d"
,
(
int
)
prec
);
*
buf
++
=
'.'
;
n
=
mrb_int2str
(
buf
,
end
-
buf
,
prec
);
buf
+=
n
;
}
...
...
mrbgems/mruby-sprintf/test/sprintf.rb
View file @
e9877bc7
...
...
@@ -8,6 +8,11 @@ assert('String#%') do
assert_equal
15
,
(
"%b"
%
(
1
<<
14
)).
size
skip
unless
Object
.
const_defined?
(
:Float
)
assert_equal
"1.0"
,
"%3.1f"
%
1.01
assert_equal
" 123456789.12"
,
"% 4.2f"
%
123456789.123456789
assert_equal
"123456789.12"
,
"%-4.2f"
%
123456789.123456789
assert_equal
"+123456789.12"
,
"%+4.2f"
%
123456789.123456789
assert_equal
"123456789.12"
,
"%04.2f"
%
123456789.123456789
assert_equal
"00000000123456789.12"
,
"%020.2f"
%
123456789.123456789
end
assert
(
'String#% with inf'
)
do
...
...
src/fmt_fp.c
View file @
e9877bc7
...
...
@@ -37,9 +37,19 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <mruby.h>
#include <mruby/string.h>
struct
fmt_args
;
typedef
void
output_func
(
struct
fmt_args
*
f
,
const
char
*
s
,
size_t
l
);
struct
fmt_args
{
mrb_state
*
mrb
;
mrb_value
str
;
output_func
*
output
;
void
*
opaque
;
};
struct
mrb_cstr
{
char
*
buf
;
size_t
len
;
};
#define MAX(a,b) ((a)>(b) ? (a) : (b))
...
...
@@ -54,15 +64,44 @@ struct fmt_args {
#define PAD_POS (1U<<(' '-' '))
#define MARK_POS (1U<<('+'-' '))
#define FLAGMASK (ALT_FORM|ZERO_PAD|LEFT_ADJ|PAD_POS|MARK_POS)
static
output_func
strcat_value
;
static
output_func
strcat_cstr
;
static
void
strcat_value
(
struct
fmt_args
*
f
,
const
char
*
s
,
size_t
l
)
{
mrb_value
str
=
*
(
mrb_value
*
)
f
->
opaque
;
mrb_str_cat
(
f
->
mrb
,
str
,
s
,
l
);
}
static
void
strcat_cstr
(
struct
fmt_args
*
f
,
const
char
*
s
,
size_t
l
)
{
struct
mrb_cstr
*
cstr
=
(
struct
mrb_cstr
*
)
f
->
opaque
;
if
(
l
>
cstr
->
len
)
{
mrb_state
*
mrb
=
f
->
mrb
;
mrb_raise
(
mrb
,
E_ARGUMENT_ERROR
,
"string buffer too small"
);
}
memcpy
(
cstr
->
buf
,
s
,
l
);
cstr
->
buf
+=
l
;
cstr
->
len
-=
l
;
}
static
void
out
(
struct
fmt_args
*
f
,
const
char
*
s
,
size_t
l
)
{
mrb_str_cat
(
f
->
mrb
,
f
->
str
,
s
,
l
);
f
->
output
(
f
,
s
,
l
);
}
#define PAD_SIZE 256
static
void
pad
(
struct
fmt_args
*
f
,
char
c
,
ptrdiff_t
w
,
ptrdiff_t
l
,
uint
8
_t
fl
)
pad
(
struct
fmt_args
*
f
,
char
c
,
ptrdiff_t
w
,
ptrdiff_t
l
,
uint
32
_t
fl
)
{
char
pad
[
PAD_SIZE
];
if
(
fl
&
(
LEFT_ADJ
|
ZERO_PAD
)
||
l
>=
w
)
return
;
...
...
@@ -92,7 +131,7 @@ typedef char compiler_defines_long_double_incorrectly[9-(int)sizeof(long double)
#endif
static
int
fmt_fp
(
struct
fmt_args
*
f
,
long
double
y
,
ptrdiff_t
p
,
uint8
_t
fl
,
int
t
)
fmt_fp
(
struct
fmt_args
*
f
,
long
double
y
,
ptrdiff_t
w
,
ptrdiff_t
p
,
uint32
_t
fl
,
int
t
)
{
uint32_t
big
[(
LDBL_MANT_DIG
+
28
)
/
29
+
1
// mantissa expansion
+
(
LDBL_MAX_EXP
+
LDBL_MANT_DIG
+
28
+
8
)
/
9
];
// exponent expansion
...
...
@@ -117,11 +156,11 @@ fmt_fp(struct fmt_args *f, long double y, ptrdiff_t p, uint8_t fl, int t)
if
(
!
isfinite
(
y
))
{
const
char
*
ss
=
(
t
&
32
)
?
"inf"
:
"INF"
;
if
(
y
!=
y
)
ss
=
(
t
&
32
)
?
"nan"
:
"NAN"
;
pad
(
f
,
' '
,
0
,
3
+
pl
,
fl
&~
ZERO_PAD
);
pad
(
f
,
' '
,
w
,
3
+
pl
,
fl
&~
ZERO_PAD
);
out
(
f
,
prefix
,
pl
);
out
(
f
,
ss
,
3
);
pad
(
f
,
' '
,
0
,
3
+
pl
,
fl
^
LEFT_ADJ
);
return
3
+
(
int
)
pl
;
pad
(
f
,
' '
,
w
,
3
+
pl
,
fl
^
LEFT_ADJ
);
return
MAX
(
w
,
3
+
(
int
)
pl
)
;
}
y
=
frexp
((
double
)
y
,
&
e2
)
*
2
;
...
...
@@ -169,14 +208,14 @@ fmt_fp(struct fmt_args *f, long double y, ptrdiff_t p, uint8_t fl, int t)
else
l
=
(
s
-
buf
)
+
(
ebuf
-
estr
);
pad
(
f
,
' '
,
0
,
pl
+
l
,
fl
);
pad
(
f
,
' '
,
w
,
pl
+
l
,
fl
);
out
(
f
,
prefix
,
pl
);
pad
(
f
,
'0'
,
0
,
pl
+
l
,
fl
^
ZERO_PAD
);
pad
(
f
,
'0'
,
w
,
pl
+
l
,
fl
^
ZERO_PAD
);
out
(
f
,
buf
,
s
-
buf
);
pad
(
f
,
'0'
,
l
-
(
ebuf
-
estr
)
-
(
s
-
buf
),
0
,
0
);
out
(
f
,
estr
,
ebuf
-
estr
);
pad
(
f
,
' '
,
0
,
pl
+
l
,
fl
^
LEFT_ADJ
);
return
(
int
)
pl
+
(
int
)
l
;
pad
(
f
,
' '
,
w
,
pl
+
l
,
fl
^
LEFT_ADJ
);
return
MAX
(
w
,
(
int
)
pl
+
(
int
)
l
)
;
}
if
(
p
<
0
)
p
=
6
;
...
...
@@ -288,9 +327,9 @@ fmt_fp(struct fmt_args *f, long double y, ptrdiff_t p, uint8_t fl, int t)
l
+=
ebuf
-
estr
;
}
pad
(
f
,
' '
,
0
,
pl
+
l
,
fl
);
pad
(
f
,
' '
,
w
,
pl
+
l
,
fl
);
out
(
f
,
prefix
,
pl
);
pad
(
f
,
'0'
,
0
,
pl
+
l
,
fl
^
ZERO_PAD
);
pad
(
f
,
'0'
,
w
,
pl
+
l
,
fl
^
ZERO_PAD
);
if
((
t
|
32
)
==
'f'
)
{
if
(
a
>
r
)
a
=
r
;
...
...
@@ -325,21 +364,33 @@ fmt_fp(struct fmt_args *f, long double y, ptrdiff_t p, uint8_t fl, int t)
out
(
f
,
estr
,
ebuf
-
estr
);
}
pad
(
f
,
' '
,
0
,
pl
+
l
,
fl
^
LEFT_ADJ
);
pad
(
f
,
' '
,
w
,
pl
+
l
,
fl
^
LEFT_ADJ
);
return
(
int
)
pl
+
(
int
)
l
;
return
MAX
(
w
,
(
int
)
pl
+
(
int
)
l
)
;
}
static
int
fmt_core
(
struct
fmt_args
*
f
,
const
char
*
fmt
,
mrb_float
flo
)
{
ptrdiff_t
p
;
ptrdiff_t
w
,
p
;
uint32_t
fl
;
if
(
*
fmt
!=
'%'
)
{
return
-
1
;
}
++
fmt
;
/* Read modifier flags */
for
(
fl
=
0
;
(
unsigned
)
*
fmt
-
' '
<
32
&&
(
FLAGMASK
&
(
1U
<<
(
*
fmt
-
' '
)));
fmt
++
)
fl
|=
1U
<<
(
*
fmt
-
' '
);
/* - and 0 flags are mutually exclusive */
if
(
fl
&
LEFT_ADJ
)
fl
&=
~
ZERO_PAD
;
for
(
w
=
0
;
ISDIGIT
(
*
fmt
);
++
fmt
)
{
w
=
10
*
w
+
(
*
fmt
-
'0'
);
}
if
(
*
fmt
==
'.'
)
{
++
fmt
;
for
(
p
=
0
;
ISDIGIT
(
*
fmt
);
++
fmt
)
{
...
...
@@ -353,29 +404,49 @@ fmt_core(struct fmt_args *f, const char *fmt, mrb_float flo)
switch
(
*
fmt
)
{
case
'e'
:
case
'f'
:
case
'g'
:
case
'a'
:
case
'E'
:
case
'F'
:
case
'G'
:
case
'A'
:
return
fmt_fp
(
f
,
flo
,
p
,
0
,
*
fmt
);
return
fmt_fp
(
f
,
flo
,
w
,
p
,
fl
,
*
fmt
);
default:
return
-
1
;
}
}
mrb_value
MRB_API
mrb_value
mrb_float_to_str
(
mrb_state
*
mrb
,
mrb_value
flo
,
const
char
*
fmt
)
{
struct
fmt_args
f
;
mrb_value
str
=
mrb_str_new_capa
(
mrb
,
24
);
f
.
mrb
=
mrb
;
f
.
str
=
mrb_str_new_capa
(
mrb
,
24
);
f
.
output
=
strcat_value
;
f
.
opaque
=
(
void
*
)
&
str
;
if
(
fmt_core
(
&
f
,
fmt
,
mrb_float
(
flo
))
<
0
)
{
mrb_raise
(
mrb
,
E_ARGUMENT_ERROR
,
"invalid format string"
);
}
return
f
.
str
;
return
str
;
}
MRB_API
int
mrb_float_to_cstr
(
mrb_state
*
mrb
,
char
*
buf
,
size_t
len
,
const
char
*
fmt
,
mrb_float
fval
)
{
struct
fmt_args
f
;
struct
mrb_cstr
cstr
;
cstr
.
buf
=
buf
;
cstr
.
len
=
len
-
1
;
/* reserve NUL terminator */
f
.
mrb
=
mrb
;
f
.
output
=
strcat_cstr
;
f
.
opaque
=
(
void
*
)
&
cstr
;
if
(
fmt_core
(
&
f
,
fmt
,
fval
)
<
0
)
{
mrb_raise
(
mrb
,
E_ARGUMENT_ERROR
,
"invalid format string"
);
}
*
cstr
.
buf
=
'\0'
;
return
cstr
.
buf
-
buf
;
}
#else
/* MRB_DISABLE_STDIO || _WIN32 || _WIN64 */
#include <mruby.h>
#include <stdio.h>
mrb_value
MRB_API
mrb_value
mrb_float_to_str
(
mrb_state
*
mrb
,
mrb_value
flo
,
const
char
*
fmt
)
{
char
buf
[
25
];
...
...
@@ -383,5 +454,11 @@ mrb_float_to_str(mrb_state *mrb, mrb_value flo, const char *fmt)
snprintf
(
buf
,
sizeof
(
buf
),
fmt
,
mrb_float
(
flo
));
return
mrb_str_new_cstr
(
mrb
,
buf
);
}
MRB_API
int
mrb_float_to_cstr
(
mrb_state
*
mrb
,
char
*
buf
,
size_t
len
,
const
char
*
fmt
,
mrb_float
fval
)
{
return
snprintf
(
buf
,
len
,
fmt
,
fval
);
}
#endif
/* MRB_DISABLE_STDIO || _WIN32 || _WIN64 */
#endif
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment