Boron 2.1.0
format.c
1/*
2 Copyright 2015,2019,2023 Karl Robillard
3
4 This file is part of the Boron programming language.
5
6 Boron is free software: you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 Boron is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with Boron. If not, see <http://www.gnu.org/licenses/>.
18*/
19
20
21static UStatus _formatString(UThread* ut, const UCell* fmt, const UCell* data,
22 UCell* res)
23{
24 static const char* padStr = "pad";
25 UBlockIt fi;
26 UBlockIt di;
27 USeriesIter si;
28 UBuffer tmp;
29 UBuffer* str;
30 UAtom atomPad = 0;
31 int pad = ' ';
32 int plen;
33 int dlen;
34 int colWidth;
35 int limit;
36
37 ur_makeStringCell( ut, UR_ENC_LATIN1, 32, res ); // gc!
38
39 if( ur_is(data, UT_BLOCK) || ur_is(data, UT_PAREN) )
40 {
41 ur_blockIt( ut, &di, data );
42 }
43 else
44 {
45 di.it = data;
46 di.end = data + 1;;
47 }
48
49 ur_blockIt( ut, &fi, fmt );
50 ur_strInit( &tmp, UR_ENC_LATIN1, 0 );
51 str = ur_buffer( res->series.buf );
52
53 ur_foreach( fi )
54 {
55 switch( ur_type(fi.it) )
56 {
57 case UT_INT:
58 colWidth = ur_int(fi.it);
59 limit = INT32_MAX;
60emit_column:
61 if( di.it >= di.end )
62 {
63 si.buf = &tmp; // Required by ur_strAppend.
64 si.it = si.end = 0;
65 dlen = tmp.used = 0;
66 }
67 else if( ur_isStringType( ur_type(di.it) ) )
68 {
69 ur_seriesSlice( ut, &si, di.it++ );
70 }
71 else
72 {
73 si.buf = &tmp;
74 tmp.used = si.it = 0;
75 ur_toText( ut, di.it++, &tmp );
76 si.end = tmp.used;
77 }
78
79 dlen = si.end - si.it;
80 if( dlen > limit )
81 {
82 dlen = limit;
83 si.end = si.it + limit;
84 }
85
86 if( colWidth < 0 )
87 {
88 for( plen = -colWidth - dlen; plen > 0; --plen )
89 ur_strAppendChar( str, pad );
90 ur_strAppend( str, si.buf, si.it, si.end );
91 }
92 else
93 {
94 ur_strAppend( str, si.buf, si.it, si.end );
95 for( plen = colWidth - dlen; plen > 0; --plen )
96 ur_strAppendChar( str, pad );
97 }
98 break;
99
100 case UT_COORD:
101 colWidth = fi.it->coord.n[0];
102 limit = fi.it->coord.n[1];
103 goto emit_column;
104
105 case UT_CHAR:
106 ur_strAppendChar( str, ur_int(fi.it) );
107 break;
108
109 case UT_STRING:
110 ur_seriesSlice( ut, &si, fi.it );
111 ur_strAppend( str, si.buf, si.it, si.end );
112 break;
113
114 case UT_WORD:
115 if( ! atomPad )
116 atomPad = ur_intern( ut, padStr, strlen(padStr) );
117 if( ur_atom(fi.it) == atomPad )
118 {
119 if( ++fi.it == fi.end )
120 goto cleanup;
121 if( ur_is(fi.it, UT_CHAR) )
122 pad = ur_int(fi.it);
123 else if( ur_is(fi.it, UT_INT) )
124 pad = ur_int(fi.it) + '0';
125 }
126 break;
127 }
128 }
129
130cleanup:
131 ur_strFree( &tmp );
132 return UR_OK;
133}
134
135
136static UStatus _formatReduced(UThread* ut, EvalFrameInvoke* ef)
137{
138 UCell tmp;
139 ur_initSeries(&tmp, UT_BLOCK, ef->userBuf);
140 return _formatString(ut, ut->stack.ptr.cell + ef->dat.i, &tmp,
141 ef->result);
142}
143
144
145/*-cf-
146 format
147 fmt block!
148 data
149 return: string!
150 group: io
151
152 Convert values to formatted string.
153
154 The format specification rules are:
155 int! Field width of the next data item.
156 If negative then right align the item in the field.
157 coord! Field width and limit of the next data item.
158 char!/string! Literal output to string.
159 'pad char! Set pad character for the following fields.
160*/
161CFUNC(cfunc_format)
162{
163 const UCell* data = a1+1;
164 if (ur_is(data, UT_BLOCK) || ur_is(data, UT_PAREN))
165 {
166 EvalFrame* ef = boron_reframeReduce(ut, data, res, _formatReduced);
167 ef->invoke.dat.i = a1 - ut->stack.ptr.cell;
168 return CFUNC_REFRAMED;
169 }
170
171 return _formatString(ut, a1, data, res);
172}
173
174
175//EOF
#define CFUNC(name)
Macro to define C functions.
Definition boron.h:57
#define ur_strFree
A string is a simple array.
Definition urlan.h:629
UBuffer * ur_makeStringCell(UThread *, int enc, int size, UCell *cell)
Generate a single string and set cell to reference it.
Definition string.c:104
void ur_strAppendChar(UBuffer *, int)
Append a single UCS2 character to a string.
Definition string.c:611
void ur_strInit(UBuffer *, int enc, int size)
Initialize buffer to type UT_STRING.
Definition string.c:430
void ur_strAppend(UBuffer *, const UBuffer *strB, UIndex itB, UIndex endB)
Append another string buffer to this string.
Definition string.c:899
void ur_seriesSlice(const UThread *, USeriesIter *si, const UCell *cell)
Set USeriesIter to series slice.
Definition env.c:1338
UIndex it
Start position.
Definition urlan.h:338
UAtom ur_intern(UThread *, const char *name, int len)
Add a single atom to the shared environment.
Definition env.c:596
const UCell * end
End position.
Definition urlan.h:388
void ur_toText(UThread *, const UCell *cell, UBuffer *str)
Append textual representation of cell to a string.
Definition env.c:1118
UIndex end
End position.
Definition urlan.h:339
const UCell * it
Start position.
Definition urlan.h:387
@ UR_OK
Returned to indicate successful evaluation/operation.
Definition urlan.h:118
#define ur_foreach(bi)
Loop over all members of an iterator struct.
Definition urlan.h:760
const UBuffer * ur_blockIt(const UThread *ut, UBlockIt *bi, const UCell *blkCell)
Set UBlockIt to the start and end of a block slice.
Definition env.c:1388
const UBuffer * buf
Buffer pointer.
Definition urlan.h:337
#define ur_buffer(n)
Macro to get buffer known to be in thread dataStore.
Definition urlan.h:750
#define ur_type(c)
Return UrlanDataType of cell.
Definition urlan.h:695
Iterator for const UCell array.
Definition urlan.h:386
The UBuffer struct holds information about a resource, usually a chunk of memory.
Definition urlan.h:266
UIndex used
This typically holds the number of elements in the buffer.
Definition urlan.h:271
UCell * cell
Array of cells.
Definition urlan.h:275
union UBuffer::@312146223224040072236377336057316010374162171270 ptr
This typically holds a pointer to a chunk of memory.
int16_t n[UR_COORD_MAX]
Holds six, 16-bit integers.
Definition urlan.h:195
UIndex buf
Buffer id.
Definition urlan.h:228
Iterator for const series of any type.
Definition urlan.h:336
The UThread struct stores the data specific to a thread of execution.
Definition urlan.h:309
A cell holds a single value of a simple type or a reference (often to a UBuffer) for a complex type.
Definition urlan.h:248
UCellCoord coord
For coord! type.
Definition urlan.h:253
UCellSeries series
For binary!, bitset!, string!, file!, block!, paren!, path! types.
Definition urlan.h:255
UStatus
Definition urlan.h:116