summaryrefslogtreecommitdiffstats
path: root/qemu/roms/ipxe/src/interface/efi/efi_strings.c
blob: 751589b466692f7641386c53549daed64bdcadfc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/*
 * Copyright (C) 2011 Michael Brown <mbrown@fensystems.co.uk>.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA.
 */

FILE_LICENCE ( GPL2_OR_LATER );

#include <stddef.h>
#include <stdarg.h>
#include <ipxe/vsprintf.h>
#include <ipxe/efi/efi_strings.h>

/** Context used by efi_vsnprintf() and friends */
struct efi_sputc_context {
	/** printf context */
	struct printf_context ctx;
	/** Buffer for formatted string (used by efi_printf_sputc()) */
	wchar_t *buf;
	/** Buffer length (used by efi_printf_sputc())
	 *
	 * Note that this is a number of wide characters, not a number
	 * of bytes.
	 */
	size_t max_wlen;
};

/**
 * Write wide character to buffer
 *
 * @v ctx		Context
 * @v c			Character
 */
static void efi_printf_sputc ( struct printf_context *ctx, unsigned int c ) {
	struct efi_sputc_context * sctx =
		container_of ( ctx, struct efi_sputc_context, ctx );

	if ( ctx->len < sctx->max_wlen )
		sctx->buf[ctx->len] = c;
}

/**
 * Write a formatted string to a wide-character buffer
 *
 * @v wbuf		Buffer into which to write the string
 * @v wsize		Size of buffer (in wide characters)
 * @v fmt		Format string
 * @v args		Arguments corresponding to the format string
 * @ret wlen		Length of formatted string (in wide characters)
 *
 * If the buffer is too small to contain the string, the returned
 * length is the length that would have been written had enough space
 * been available.
 */
int efi_vsnprintf ( wchar_t *wbuf, size_t wsize, const char *fmt,
		    va_list args ) {
	struct efi_sputc_context sctx;
	size_t wlen;
	size_t wend;

	/* Hand off to vcprintf */
	sctx.ctx.handler = efi_printf_sputc;
	sctx.buf = wbuf;
	sctx.max_wlen = wsize;
	wlen = vcprintf ( &sctx.ctx, fmt, args );

	/* Add trailing NUL */
	if ( wsize ) {
		wend = wsize - 1;
		if ( wlen < wend )
			wend = wlen;
		wbuf[wend] = '\0';
	}

	return wlen;
}

/**
 * Write a formatted string to a buffer
 *
 * @v wbuf		Buffer into which to write the string
 * @v wsize		Size of buffer (in wide characters)
 * @v fmt		Format string
 * @v ...		Arguments corresponding to the format string
 * @ret wlen		Length of formatted string (in wide characters)
 */
int efi_snprintf ( wchar_t *wbuf, size_t wsize, const char *fmt, ... ) {
	va_list args;
	int i;

	va_start ( args, fmt );
	i = efi_vsnprintf ( wbuf, wsize, fmt, args );
	va_end ( args );
	return i;
}

/**
 * Version of efi_vsnprintf() that accepts a signed buffer size
 *
 * @v wbuf		Buffer into which to write the string
 * @v swsize		Size of buffer (in wide characters)
 * @v fmt		Format string
 * @v args		Arguments corresponding to the format string
 * @ret wlen		Length of formatted string (in wide characters)
 */
int efi_vssnprintf ( wchar_t *wbuf, ssize_t swsize, const char *fmt,
		     va_list args ) {

	/* Treat negative buffer size as zero buffer size */
	if ( swsize < 0 )
		swsize = 0;

	/* Hand off to vsnprintf */
	return efi_vsnprintf ( wbuf, swsize, fmt, args );
}

/**
 * Version of efi_vsnprintf() that accepts a signed buffer size
 *
 * @v wbuf		Buffer into which to write the string
 * @v swsize		Size of buffer (in wide characters)
 * @v fmt		Format string
 * @v ...		Arguments corresponding to the format string
 * @ret wlen		Length of formatted string (in wide characters)
 */
int efi_ssnprintf ( wchar_t *wbuf, ssize_t swsize, const char *fmt, ... ) {
	va_list args;
	int len;

	/* Hand off to vssnprintf */
	va_start ( args, fmt );
	len = efi_vssnprintf ( wbuf, swsize, fmt, args );
	va_end ( args );
	return len;
}