Files
openflow/lib/util.c
T
2009-06-29 05:03:42 -07:00

298 lines
6.9 KiB
C

/* Copyright (c) 2008 The Board of Trustees of The Leland Stanford
* Junior University
*
* We are making the OpenFlow specification and associated documentation
* (Software) available for public use and benefit with the expectation
* that others will use, modify and enhance the Software and contribute
* those enhancements back to the community. However, since we would
* like to make the Software available for broadest use, with as few
* restrictions as possible permission is hereby granted, free of
* charge, to any person obtaining a copy of this Software to deal in
* the Software under the copyrights without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* The name and trademarks of copyright holder(s) may NOT be used in
* advertising or publicity pertaining to the Software or any
* derivatives without specific, written prior permission.
*/
#include <config.h>
#include "util.h"
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const char *program_name;
void
out_of_memory(void)
{
ofp_fatal(0, "virtual memory exhausted");
}
void *
xcalloc(size_t count, size_t size)
{
void *p = count && size ? calloc(count, size) : malloc(1);
if (p == NULL) {
out_of_memory();
}
return p;
}
void *
xmalloc(size_t size)
{
void *p = malloc(size ? size : 1);
if (p == NULL) {
out_of_memory();
}
return p;
}
void *
xrealloc(void *p, size_t size)
{
p = realloc(p, size ? size : 1);
if (p == NULL) {
out_of_memory();
}
return p;
}
void *
xmemdup(const void *p_, size_t size)
{
void *p = xmalloc(size);
memcpy(p, p_, size);
return p;
}
char *
xmemdup0(const char *p_, size_t length)
{
char *p = xmalloc(length + 1);
memcpy(p, p_, length);
p[length] = '\0';
return p;
}
char *
xstrdup(const char *s)
{
return xmemdup0(s, strlen(s));
}
char *
xvasprintf(const char *format, va_list args)
{
va_list args2;
size_t needed;
char *s;
va_copy(args2, args);
needed = vsnprintf(NULL, 0, format, args);
s = xmalloc(needed + 1);
vsnprintf(s, needed + 1, format, args2);
va_end(args2);
return s;
}
void *
x2nrealloc(void *p, size_t *n, size_t s)
{
*n = *n == 0 ? 1 : 2 * *n;
return xrealloc(p, *n * s);
}
char *
xasprintf(const char *format, ...)
{
va_list args;
char *s;
va_start(args, format);
s = xvasprintf(format, args);
va_end(args);
return s;
}
void
strlcpy(char *dst, const char *src, size_t size)
{
if (size > 0) {
size_t n = strlen(src);
size_t n_copy = MIN(n, size - 1);
memcpy(dst, src, n_copy);
dst[n_copy] = '\0';
}
}
void
ofp_fatal(int err_no, const char *format, ...)
{
va_list args;
fprintf(stderr, "%s: ", program_name);
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
if (err_no != 0)
fprintf(stderr, " (%s)", strerror(err_no));
putc('\n', stderr);
exit(EXIT_FAILURE);
}
void
ofp_error(int err_no, const char *format, ...)
{
int save_errno = errno;
va_list args;
fprintf(stderr, "%s: ", program_name);
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
if (err_no != 0)
fprintf(stderr, " (%s)", strerror(err_no));
putc('\n', stderr);
errno = save_errno;
}
/* Sets program_name based on 'argv0'. Should be called at the beginning of
* main(), as "set_program_name(argv[0]);". */
void set_program_name(const char *argv0)
{
const char *slash = strrchr(argv0, '/');
program_name = slash ? slash + 1 : argv0;
}
/* Writes the 'size' bytes in 'buf' to 'stream' as hex bytes arranged 16 per
* line. Numeric offsets are also included, starting at 'ofs' for the first
* byte in 'buf'. If 'ascii' is true then the corresponding ASCII characters
* are also rendered alongside. */
void
ofp_hex_dump(FILE *stream, const void *buf_, size_t size,
uintptr_t ofs, bool ascii)
{
const uint8_t *buf = buf_;
const size_t per_line = 16; /* Maximum bytes per line. */
while (size > 0)
{
size_t start, end, n;
size_t i;
/* Number of bytes on this line. */
start = ofs % per_line;
end = per_line;
if (end - start > size)
end = start + size;
n = end - start;
/* Print line. */
fprintf(stream, "%08jx ", (uintmax_t) ROUND_DOWN(ofs, per_line));
for (i = 0; i < start; i++)
fprintf(stream, " ");
for (; i < end; i++)
fprintf(stream, "%02hhx%c",
buf[i - start], i == per_line / 2 - 1? '-' : ' ');
if (ascii)
{
for (; i < per_line; i++)
fprintf(stream, " ");
fprintf(stream, "|");
for (i = 0; i < start; i++)
fprintf(stream, " ");
for (; i < end; i++) {
int c = buf[i - start];
putc(c >= 32 && c < 127 ? c : '.', stream);
}
for (; i < per_line; i++)
fprintf(stream, " ");
fprintf(stream, "|");
}
fprintf(stream, "\n");
ofs += n;
buf += n;
size -= n;
}
}
bool
str_to_int(const char *s, int base, int *i)
{
long long ll;
bool ok = str_to_llong(s, base, &ll);
*i = ll;
return ok;
}
bool
str_to_long(const char *s, int base, long *li)
{
long long ll;
bool ok = str_to_llong(s, base, &ll);
*li = ll;
return ok;
}
bool
str_to_llong(const char *s, int base, long long *x)
{
int save_errno = errno;
char *tail;
errno = 0;
*x = strtoll(s, &tail, base);
if (errno == EINVAL || errno == ERANGE || tail == s || *tail != '\0') {
errno = save_errno;
*x = 0;
return false;
} else {
errno = save_errno;
return true;
}
}
bool
str_to_uint(const char *s, int base, unsigned int *u)
{
return str_to_int(s, base, (int *) u);
}
bool
str_to_ulong(const char *s, int base, unsigned long *ul)
{
return str_to_long(s, base, (long *) ul);
}
bool
str_to_ullong(const char *s, int base, unsigned long long *ull)
{
return str_to_llong(s, base, (long long *) ull);
}