Source

pebble time zone watch face / lib / src / sprintf.c

/** \file
 * Simple version of sprintf to avoid bringing in all of libc.
 *
 * Only supported: %d, %s, %x
 */
//#include <stdio.h>
#include <stdarg.h>
#include "pebble_th.h"


static int
fmt_int(
	char * buf,
	unsigned x,
	int base,
	int width,
	int leading_zero
)
{
	(void) width;
	(void) leading_zero;

	char tmp[16];
	int offset = 0;
	do {
		int digit;
		if (base == 16)
		{
			digit = x % 16;
			x /= 16;
		} else
		//if (base == 10) // do it always
		{
			digit = x % 10;
			x /= 10;
		}

		char c;
		if (digit >=  0xA)
			c = digit + 'A' - 0xA;
		else
			c = digit + '0';

		tmp[offset++] = c;
	} while (x);

	tmp[offset] = '\0';

	// reverse it into place
	int i;
	for (i = 0 ; i < offset ; i++)
		buf[i] = tmp[offset - i - 1];

	return offset;
}


int
pebble_sprintf(
	char * buf,
	const char * fmt,
	...
)
{
	va_list ap;
	va_start(ap, fmt);
	int offset = 0;

	while (1)
	{
		const char c = *fmt++;
		if (c == '\0')
			break;
		if (c != '%')
		{
			buf[offset++] = c;
			continue;
		}

		// Look for a digit
		int leading_zero = 0;
		int width = 0;

		char n = *fmt;
		if ('0' <= n && n <= '9')
		{
			if (n == '0')
			{
				leading_zero = 1;
				n = *++fmt;
			}

			while ('0' <= n && n <= '9')
			{
				width = width * 10 + n - '0';
				n = *++fmt;
			}
		}

		// width and leading zero are set.
		// fmt now points at the type
		const char type = *fmt++;

		switch (type)
		{
		case 's':
		{
			// Width and zero are ignored for now
			const char * s = va_arg(ap, const char *);
			while (1)
			{
				const char c = *s++;
				if (c == '\0')
					break;
				buf[offset++] = c;
			}
			break;
		}

		case 'd':
		{
			const int x = va_arg(ap, int);
			offset += fmt_int(buf + offset, x, 10, width, leading_zero);
			break;
		}
		case 'x':
		{
			const int x = va_arg(ap, int);
			offset += fmt_int(buf + offset, x, 16, width, leading_zero);
			break;
		}
		case '%':
			buf[offset++] = '%';
			break;
		default:
		{
			va_arg(ap, int);
			buf[offset++] = '?';
			break;
		}
		}
	}

	va_end(ap);

	buf[offset] = '\0';
	return offset;
}

#if 0
int main(void)
{
	char buf[64];

	pebble_sprintf(buf, "hello: foo %s %% %d 0x%x 0x%08x\n",
		"bar",
		123,
		0x9999,
		0xdeadbeef
	);

	printf("%s", buf);
	return 0;
}
#endif
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.