Move all external code to lib/external.
This commit is contained in:
2063
lib/external/fetch/common.c
vendored
Normal file
2063
lib/external/fetch/common.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
174
lib/external/fetch/common.h
vendored
Normal file
174
lib/external/fetch/common.h
vendored
Normal file
@@ -0,0 +1,174 @@
|
||||
/* $FreeBSD: rev 267133 $ */
|
||||
/* $NetBSD: common.h,v 1.23 2014/01/08 20:25:34 joerg Exp $ */
|
||||
/*-
|
||||
* Copyright (c) 1998-2014 Dag-Erling Smorgrav
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer
|
||||
* in this position and unchanged.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _COMMON_H_INCLUDED
|
||||
#define _COMMON_H_INCLUDED
|
||||
|
||||
#define FTP_DEFAULT_PORT 21
|
||||
#define HTTP_DEFAULT_PORT 80
|
||||
#define HTTPS_DEFAULT_PORT 443
|
||||
#define FTP_DEFAULT_PROXY_PORT 21
|
||||
#define HTTP_DEFAULT_PROXY_PORT 3128
|
||||
#define SOCKS5_DEFAULT_PORT 1080
|
||||
|
||||
#define SOCKS5_VERSION 0x05
|
||||
#define SOCKS5_PASS_VERSION 0x01
|
||||
|
||||
#define SOCKS5_NO_AUTH 0x00
|
||||
#define SOCKS5_USER_PASS 0x02
|
||||
#define SOCKS5_AUTH_SUCCESS 0x00
|
||||
#define SOCKS5_NO_METHOD 0xFF
|
||||
|
||||
#define SOCKS5_TCP_STREAM 0x01
|
||||
|
||||
#define SOCKS5_ATYPE_IPV4 0x01
|
||||
#define SOCKS5_ATYPE_DOMAIN 0x03
|
||||
#define SOCKS5_ATYPE_IPV6 0x04
|
||||
|
||||
#define SOCKS5_REPLY_SUCCESS 0x00
|
||||
#define SOCKS5_REPLY_FAILURE 0x01
|
||||
#define SOCKS5_REPLY_DENY 0x02
|
||||
#define SOCKS5_REPLY_NO_NET 0x03
|
||||
#define SOCKS5_REPLY_NO_HOST 0x04
|
||||
#define SOCKS5_REPLY_REFUSED 0x05
|
||||
#define SOCKS5_REPLY_TIMEOUT 0x06
|
||||
#define SOCKS5_REPLY_CMD_NOTSUP 0x07
|
||||
#define SOCKS5_REPLY_ADR_NOTSUP 0x08
|
||||
|
||||
#ifdef WITH_SSL
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/err.h>
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ >= 3
|
||||
#define LIBFETCH_PRINTFLIKE(fmtarg, firstvararg) \
|
||||
__attribute__((__format__ (__printf__, fmtarg, firstvararg)))
|
||||
#else
|
||||
#define LIBFETCH_PRINTFLIKE(fmtarg, firstvararg)
|
||||
#endif
|
||||
|
||||
#if !defined(__sun) && !defined(__hpux) && !defined(__INTERIX) && \
|
||||
!defined(__digital__) && !defined(__linux) && !defined(__MINT__) && \
|
||||
!defined(__sgi) && !defined(__minix) && !defined(__CYGWIN__)
|
||||
#define HAVE_SA_LEN
|
||||
#endif
|
||||
|
||||
/* Connection */
|
||||
typedef struct fetchconn conn_t;
|
||||
|
||||
struct fetchconn {
|
||||
int sd; /* socket descriptor */
|
||||
char *buf; /* buffer */
|
||||
size_t bufsize; /* buffer size */
|
||||
size_t buflen; /* length of buffer contents */
|
||||
char *next_buf; /* pending buffer, e.g. after getln */
|
||||
size_t next_len; /* size of pending buffer */
|
||||
int err; /* last protocol reply code */
|
||||
#ifdef WITH_SSL
|
||||
SSL *ssl; /* SSL handle */
|
||||
SSL_CTX *ssl_ctx; /* SSL context */
|
||||
X509 *ssl_cert; /* server certificate */
|
||||
#endif
|
||||
|
||||
char *ftp_home;
|
||||
|
||||
struct url *cache_url;
|
||||
int cache_af;
|
||||
int (*cache_close)(conn_t *);
|
||||
conn_t *next_cached;
|
||||
};
|
||||
|
||||
/* Structure used for error message lists */
|
||||
struct fetcherr {
|
||||
const int num;
|
||||
const int cat;
|
||||
const char *string;
|
||||
};
|
||||
|
||||
void fetch_seterr(struct fetcherr *, int);
|
||||
void fetch_syserr(void);
|
||||
void fetch_info(const char *, ...) LIBFETCH_PRINTFLIKE(1, 2);
|
||||
int fetch_default_port(const char *);
|
||||
int fetch_default_proxy_port(const char *);
|
||||
int fetch_bind(int, int, const char *);
|
||||
conn_t *fetch_cache_get(const struct url *, int);
|
||||
void fetch_cache_put(conn_t *, int (*)(conn_t *));
|
||||
int fetch_socks5(conn_t *, struct url *, struct url *, int);
|
||||
conn_t *fetch_connect(struct url *, int, int);
|
||||
conn_t *fetch_reopen(int);
|
||||
#ifdef WITH_SSL
|
||||
int fetch_ssl_cb_verify_crt(int, X509_STORE_CTX*);
|
||||
#endif
|
||||
int fetch_ssl(conn_t *, const struct url *, int);
|
||||
ssize_t fetch_read(conn_t *, char *, size_t);
|
||||
int fetch_getln(conn_t *);
|
||||
ssize_t fetch_write(conn_t *, const void *, size_t);
|
||||
int fetch_close(conn_t *);
|
||||
int fetch_add_entry(struct url_list *, struct url *, const char *, int);
|
||||
int fetch_netrc_auth(struct url *url);
|
||||
int fetch_no_proxy_match(const char *);
|
||||
int fetch_urlpath_safe(char);
|
||||
|
||||
#define ftp_seterr(n) fetch_seterr(ftp_errlist, n)
|
||||
#define http_seterr(n) fetch_seterr(http_errlist, n)
|
||||
#define netdb_seterr(n) fetch_seterr(netdb_errlist, n)
|
||||
#define url_seterr(n) fetch_seterr(url_errlist, n)
|
||||
|
||||
fetchIO *fetchIO_unopen(void *, ssize_t (*)(void *, void *, size_t),
|
||||
ssize_t (*)(void *, const void *, size_t), void (*)(void *));
|
||||
|
||||
/*
|
||||
* I don't really like exporting http_request() and ftp_request(),
|
||||
* but the HTTP and FTP code occasionally needs to cross-call
|
||||
* eachother, and this saves me from adding a lot of special-case code
|
||||
* to handle those cases.
|
||||
*
|
||||
* Note that _*_request() free purl, which is way ugly but saves us a
|
||||
* whole lot of trouble.
|
||||
*/
|
||||
fetchIO *http_request(struct url *, const char *,
|
||||
struct url_stat *, struct url *, const char *);
|
||||
fetchIO *ftp_request(struct url *, const char *, const char *,
|
||||
struct url_stat *, struct url *, const char *);
|
||||
|
||||
|
||||
/*
|
||||
* Check whether a particular flag is set
|
||||
*/
|
||||
#define CHECK_FLAG(x) (flags && strchr(flags, (x)))
|
||||
|
||||
#ifndef __UNCONST
|
||||
#define __UNCONST(a) ((void *)(unsigned long)(const void *)(a))
|
||||
#endif
|
||||
|
||||
#endif
|
||||
11
lib/external/fetch/errlist.sh
vendored
Executable file
11
lib/external/fetch/errlist.sh
vendored
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
# $NetBSD: errlist.sh,v 1.2 2008/10/06 12:58:29 joerg Exp $
|
||||
|
||||
printf "static struct fetcherr $1[] = {\n"
|
||||
while read code type msg; do
|
||||
[ "${code}" = "#" ] && continue
|
||||
printf "\t{ ${code}, FETCH_${type}, \"${msg}\" },\n"
|
||||
done < $3
|
||||
|
||||
printf "\t{ -1, FETCH_UNKNOWN, \"Unknown $2 error\" }\n"
|
||||
printf "};\n"
|
||||
680
lib/external/fetch/fetch.c
vendored
Normal file
680
lib/external/fetch/fetch.c
vendored
Normal file
@@ -0,0 +1,680 @@
|
||||
/* $FreeBSD: rev 252375 $ */
|
||||
/* $NetBSD: fetch.c,v 1.19 2009/08/11 20:48:06 joerg Exp $ */
|
||||
/*-
|
||||
* Copyright (c) 1998-2004 Dag-Erling Coïdan Smørav
|
||||
* Copyright (c) 2008 Joerg Sonnenberger <joerg@NetBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer
|
||||
* in this position and unchanged.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "compat.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
|
||||
#include "fetch.h"
|
||||
#include "common.h"
|
||||
|
||||
auth_t fetchAuthMethod;
|
||||
int fetchLastErrCode;
|
||||
char fetchLastErrString[MAXERRSTRING];
|
||||
int fetchTimeout;
|
||||
int fetchConnTimeout = 300 * 1000;
|
||||
int fetchConnDelay = 250;
|
||||
volatile int fetchRestartCalls = 1;
|
||||
int fetchDebug;
|
||||
|
||||
|
||||
/*** Local data **************************************************************/
|
||||
|
||||
/*
|
||||
* Error messages for parser errors
|
||||
*/
|
||||
#define URL_MALFORMED 1
|
||||
#define URL_BAD_SCHEME 2
|
||||
#define URL_BAD_PORT 3
|
||||
static struct fetcherr url_errlist[] = {
|
||||
{ URL_MALFORMED, FETCH_URL, "Malformed URL" },
|
||||
{ URL_BAD_SCHEME, FETCH_URL, "Invalid URL scheme" },
|
||||
{ URL_BAD_PORT, FETCH_URL, "Invalid server port" },
|
||||
{ -1, FETCH_UNKNOWN, "Unknown parser error" }
|
||||
};
|
||||
|
||||
|
||||
/*** Public API **************************************************************/
|
||||
|
||||
/*
|
||||
* Select the appropriate protocol for the URL scheme, and return a
|
||||
* read-only stream connected to the document referenced by the URL.
|
||||
* Also fill out the struct url_stat.
|
||||
*/
|
||||
fetchIO *
|
||||
fetchXGet(struct url *URL, struct url_stat *us, const char *flags)
|
||||
{
|
||||
|
||||
if (us != NULL) {
|
||||
us->size = -1;
|
||||
us->atime = us->mtime = 0;
|
||||
}
|
||||
if (strcasecmp(URL->scheme, SCHEME_FILE) == 0)
|
||||
return (fetchXGetFile(URL, us, flags));
|
||||
else if (strcasecmp(URL->scheme, SCHEME_FTP) == 0)
|
||||
return (fetchXGetFTP(URL, us, flags));
|
||||
else if (strcasecmp(URL->scheme, SCHEME_HTTP) == 0)
|
||||
return (fetchXGetHTTP(URL, us, flags));
|
||||
else if (strcasecmp(URL->scheme, SCHEME_HTTPS) == 0)
|
||||
return (fetchXGetHTTP(URL, us, flags));
|
||||
url_seterr(URL_BAD_SCHEME);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Select the appropriate protocol for the URL scheme, and return a
|
||||
* read-only stream connected to the document referenced by the URL.
|
||||
*/
|
||||
fetchIO *
|
||||
fetchGet(struct url *URL, const char *flags)
|
||||
{
|
||||
return (fetchXGet(URL, NULL, flags));
|
||||
}
|
||||
|
||||
/*
|
||||
* Select the appropriate protocol for the URL scheme, and return a
|
||||
* write-only stream connected to the document referenced by the URL.
|
||||
*/
|
||||
fetchIO *
|
||||
fetchPut(struct url *URL, const char *flags)
|
||||
{
|
||||
|
||||
if (strcasecmp(URL->scheme, SCHEME_FILE) == 0)
|
||||
return (fetchPutFile(URL, flags));
|
||||
else if (strcasecmp(URL->scheme, SCHEME_FTP) == 0)
|
||||
return (fetchPutFTP(URL, flags));
|
||||
else if (strcasecmp(URL->scheme, SCHEME_HTTP) == 0)
|
||||
return (fetchPutHTTP(URL, flags));
|
||||
else if (strcasecmp(URL->scheme, SCHEME_HTTPS) == 0)
|
||||
return (fetchPutHTTP(URL, flags));
|
||||
url_seterr(URL_BAD_SCHEME);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Select the appropriate protocol for the URL scheme, and return the
|
||||
* size of the document referenced by the URL if it exists.
|
||||
*/
|
||||
int
|
||||
fetchStat(struct url *URL, struct url_stat *us, const char *flags)
|
||||
{
|
||||
|
||||
if (us != NULL) {
|
||||
us->size = -1;
|
||||
us->atime = us->mtime = 0;
|
||||
}
|
||||
if (strcasecmp(URL->scheme, SCHEME_FILE) == 0)
|
||||
return (fetchStatFile(URL, us, flags));
|
||||
else if (strcasecmp(URL->scheme, SCHEME_FTP) == 0)
|
||||
return (fetchStatFTP(URL, us, flags));
|
||||
else if (strcasecmp(URL->scheme, SCHEME_HTTP) == 0)
|
||||
return (fetchStatHTTP(URL, us, flags));
|
||||
else if (strcasecmp(URL->scheme, SCHEME_HTTPS) == 0)
|
||||
return (fetchStatHTTP(URL, us, flags));
|
||||
url_seterr(URL_BAD_SCHEME);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Select the appropriate protocol for the URL scheme, and return a
|
||||
* list of files in the directory pointed to by the URL.
|
||||
*/
|
||||
int
|
||||
fetchList(struct url_list *ue, struct url *URL, const char *pattern,
|
||||
const char *flags)
|
||||
{
|
||||
|
||||
if (strcasecmp(URL->scheme, SCHEME_FILE) == 0)
|
||||
return (fetchListFile(ue, URL, pattern, flags));
|
||||
else if (strcasecmp(URL->scheme, SCHEME_FTP) == 0)
|
||||
return (fetchListFTP(ue, URL, pattern, flags));
|
||||
else if (strcasecmp(URL->scheme, SCHEME_HTTP) == 0)
|
||||
return (fetchListHTTP(ue, URL, pattern, flags));
|
||||
else if (strcasecmp(URL->scheme, SCHEME_HTTPS) == 0)
|
||||
return (fetchListHTTP(ue, URL, pattern, flags));
|
||||
url_seterr(URL_BAD_SCHEME);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to parse the given URL; if successful, call fetchXGet().
|
||||
*/
|
||||
fetchIO *
|
||||
fetchXGetURL(const char *URL, struct url_stat *us, const char *flags)
|
||||
{
|
||||
struct url *u;
|
||||
fetchIO *f;
|
||||
|
||||
if ((u = fetchParseURL(URL)) == NULL)
|
||||
return (NULL);
|
||||
|
||||
f = fetchXGet(u, us, flags);
|
||||
|
||||
fetchFreeURL(u);
|
||||
return (f);
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to parse the given URL; if successful, call fetchGet().
|
||||
*/
|
||||
fetchIO *
|
||||
fetchGetURL(const char *URL, const char *flags)
|
||||
{
|
||||
return (fetchXGetURL(URL, NULL, flags));
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to parse the given URL; if successful, call fetchPut().
|
||||
*/
|
||||
fetchIO *
|
||||
fetchPutURL(const char *URL, const char *flags)
|
||||
{
|
||||
struct url *u;
|
||||
fetchIO *f;
|
||||
|
||||
if ((u = fetchParseURL(URL)) == NULL)
|
||||
return (NULL);
|
||||
|
||||
f = fetchPut(u, flags);
|
||||
|
||||
fetchFreeURL(u);
|
||||
return (f);
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to parse the given URL; if successful, call fetchStat().
|
||||
*/
|
||||
int
|
||||
fetchStatURL(const char *URL, struct url_stat *us, const char *flags)
|
||||
{
|
||||
struct url *u;
|
||||
int s;
|
||||
|
||||
if ((u = fetchParseURL(URL)) == NULL)
|
||||
return (-1);
|
||||
|
||||
s = fetchStat(u, us, flags);
|
||||
|
||||
fetchFreeURL(u);
|
||||
return (s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to parse the given URL; if successful, call fetchList().
|
||||
*/
|
||||
int
|
||||
fetchListURL(struct url_list *ue, const char *URL, const char *pattern,
|
||||
const char *flags)
|
||||
{
|
||||
struct url *u;
|
||||
int rv;
|
||||
|
||||
if ((u = fetchParseURL(URL)) == NULL)
|
||||
return -1;
|
||||
|
||||
rv = fetchList(ue, u, pattern, flags);
|
||||
|
||||
fetchFreeURL(u);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make a URL
|
||||
*/
|
||||
struct url *
|
||||
fetchMakeURL(const char *scheme, const char *host, int port, const char *doc,
|
||||
const char *user, const char *pwd)
|
||||
{
|
||||
struct url *u;
|
||||
|
||||
if (!scheme || (!host && !doc)) {
|
||||
url_seterr(URL_MALFORMED);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (port < 0 || port > 65535) {
|
||||
url_seterr(URL_BAD_PORT);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* allocate struct url */
|
||||
if ((u = calloc(1, sizeof(*u))) == NULL) {
|
||||
fetch_syserr();
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if ((u->doc = strdup(doc ? doc : "/")) == NULL) {
|
||||
fetch_syserr();
|
||||
free(u);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
#define seturl(x) snprintf(u->x, sizeof(u->x), "%s", x)
|
||||
seturl(scheme);
|
||||
seturl(host);
|
||||
seturl(user);
|
||||
seturl(pwd);
|
||||
#undef seturl
|
||||
u->port = port;
|
||||
|
||||
return (u);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return value of the given hex digit.
|
||||
*/
|
||||
static int
|
||||
fetch_hexval(char ch)
|
||||
{
|
||||
if (ch >= '0' && ch <= '9')
|
||||
return (ch - '0');
|
||||
else if (ch >= 'a' && ch <= 'f')
|
||||
return (ch - 'a' + 10);
|
||||
else if (ch >= 'A' && ch <= 'F')
|
||||
return (ch - 'A' + 10);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode percent-encoded URL component from src into dst, stopping at end
|
||||
* of string, or at @ or : separators. Returns a pointer to the unhandled
|
||||
* part of the input string (null terminator, @, or :). No terminator is
|
||||
* written to dst (it is the caller's responsibility).
|
||||
*/
|
||||
static const char *
|
||||
fetch_pctdecode(char *dst, const char *src, size_t dlen)
|
||||
{
|
||||
int d1, d2;
|
||||
char c;
|
||||
const char *s;
|
||||
|
||||
for (s = src; *s != '\0' && *s != '@' && *s != ':'; s++) {
|
||||
if (s[0] == '%' && (d1 = fetch_hexval(s[1])) >= 0 &&
|
||||
(d2 = fetch_hexval(s[2])) >= 0 && (d1 > 0 || d2 > 0)) {
|
||||
c = d1 << 4 | d2;
|
||||
s += 2;
|
||||
} else {
|
||||
c = *s;
|
||||
}
|
||||
if (dlen-- > 0)
|
||||
*dst++ = c;
|
||||
else
|
||||
return (NULL);
|
||||
}
|
||||
return (s);
|
||||
}
|
||||
|
||||
int
|
||||
fetch_urlpath_safe(char x)
|
||||
{
|
||||
if ((x >= '0' && x <= '9') || (x >= 'A' && x <= 'Z') ||
|
||||
(x >= 'a' && x <= 'z'))
|
||||
return 1;
|
||||
|
||||
switch (x) {
|
||||
case '$':
|
||||
case '-':
|
||||
case '_':
|
||||
case '.':
|
||||
case '+':
|
||||
case '!':
|
||||
case '*':
|
||||
case '\'':
|
||||
case '(':
|
||||
case ')':
|
||||
case ',':
|
||||
/* The following are allowed in segment and path components: */
|
||||
case '?':
|
||||
case ':':
|
||||
case '@':
|
||||
case '&':
|
||||
case '=':
|
||||
case '/':
|
||||
case ';':
|
||||
/* If something is already quoted... */
|
||||
case '%':
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy an existing URL.
|
||||
*/
|
||||
struct url *
|
||||
fetchCopyURL(const struct url *src)
|
||||
{
|
||||
struct url *dst;
|
||||
char *doc;
|
||||
|
||||
/* allocate struct url */
|
||||
if ((dst = malloc(sizeof(*dst))) == NULL) {
|
||||
fetch_syserr();
|
||||
return (NULL);
|
||||
}
|
||||
if ((doc = strdup(src->doc)) == NULL) {
|
||||
fetch_syserr();
|
||||
free(dst);
|
||||
return (NULL);
|
||||
}
|
||||
*dst = *src;
|
||||
dst->doc = doc;
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
/*
|
||||
* Split an URL into components. URL syntax is:
|
||||
* [method:/][/[user[:pwd]@]host[:port]/][document]
|
||||
* This almost, but not quite, RFC1738 URL syntax.
|
||||
*/
|
||||
struct url *
|
||||
fetchParseURL(const char *URL)
|
||||
{
|
||||
const char *p, *q;
|
||||
struct url *u;
|
||||
size_t i, count;
|
||||
int pre_quoted;
|
||||
|
||||
/* allocate struct url */
|
||||
if ((u = calloc(1, sizeof(*u))) == NULL) {
|
||||
fetch_syserr();
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (*URL == '/') {
|
||||
pre_quoted = 0;
|
||||
strcpy(u->scheme, SCHEME_FILE);
|
||||
p = URL;
|
||||
goto quote_doc;
|
||||
}
|
||||
if (strncmp(URL, "file:", 5) == 0) {
|
||||
pre_quoted = 1;
|
||||
strcpy(u->scheme, SCHEME_FILE);
|
||||
URL += 5;
|
||||
if (URL[0] != '/' || URL[1] != '/' || URL[2] != '/') {
|
||||
url_seterr(URL_MALFORMED);
|
||||
goto ouch;
|
||||
}
|
||||
URL += 2;
|
||||
p = URL;
|
||||
goto quote_doc;
|
||||
}
|
||||
if (strncmp(URL, "http:", 5) == 0 ||
|
||||
strncmp(URL, "https:", 6) == 0) {
|
||||
pre_quoted = 1;
|
||||
if (URL[4] == ':') {
|
||||
strcpy(u->scheme, SCHEME_HTTP);
|
||||
URL += 5;
|
||||
} else {
|
||||
strcpy(u->scheme, SCHEME_HTTPS);
|
||||
URL += 6;
|
||||
}
|
||||
|
||||
if (URL[0] != '/' || URL[1] != '/') {
|
||||
url_seterr(URL_MALFORMED);
|
||||
goto ouch;
|
||||
}
|
||||
URL += 2;
|
||||
goto find_user;
|
||||
}
|
||||
if (strncmp(URL, "ftp:", 4) == 0) {
|
||||
pre_quoted = 1;
|
||||
strcpy(u->scheme, SCHEME_FTP);
|
||||
URL += 4;
|
||||
if (URL[0] != '/' || URL[1] != '/') {
|
||||
url_seterr(URL_MALFORMED);
|
||||
goto ouch;
|
||||
}
|
||||
URL += 2;
|
||||
goto find_user;
|
||||
}
|
||||
if (strncmp(URL, "socks5:", 7) == 0) {
|
||||
pre_quoted = 1;
|
||||
strcpy(u->scheme, SCHEME_SOCKS5);
|
||||
URL += 7;
|
||||
if (URL[0] != '/' || URL[1] != '/') {
|
||||
url_seterr(URL_MALFORMED);
|
||||
goto ouch;
|
||||
}
|
||||
URL += 2;
|
||||
goto find_user;
|
||||
}
|
||||
|
||||
url_seterr(URL_BAD_SCHEME);
|
||||
goto ouch;
|
||||
|
||||
find_user:
|
||||
p = strpbrk(URL, "/@");
|
||||
if (p != NULL && *p == '@') {
|
||||
/* username */
|
||||
q = fetch_pctdecode(u->user, URL, URL_USERLEN);
|
||||
if (q == NULL)
|
||||
goto ouch;
|
||||
/* password */
|
||||
if (*q == ':') {
|
||||
q = fetch_pctdecode(u->pwd, q + 1, URL_PWDLEN);
|
||||
if (q == NULL)
|
||||
goto ouch;
|
||||
}
|
||||
p++;
|
||||
} else {
|
||||
p = URL;
|
||||
}
|
||||
|
||||
/* hostname */
|
||||
#ifdef INET6
|
||||
if (*p == '[' && (q = strchr(p + 1, ']')) != NULL &&
|
||||
(*++q == '\0' || *q == '/' || *q == ':')) {
|
||||
if ((i = q - p - 2) > URL_HOSTLEN)
|
||||
i = URL_HOSTLEN;
|
||||
strncpy(u->host, ++p, i);
|
||||
p = q;
|
||||
} else
|
||||
#endif
|
||||
for (i = 0; *p && (*p != '/') && (*p != ':'); p++)
|
||||
if (i < URL_HOSTLEN)
|
||||
u->host[i++] = *p;
|
||||
|
||||
/* port */
|
||||
if (*p == ':') {
|
||||
for (q = ++p; *q && (*q != '/'); q++)
|
||||
if (isdigit((unsigned char)*q))
|
||||
u->port = u->port * 10 + (*q - '0');
|
||||
else {
|
||||
/* invalid port */
|
||||
url_seterr(URL_BAD_PORT);
|
||||
goto ouch;
|
||||
}
|
||||
p = q;
|
||||
}
|
||||
|
||||
/* document */
|
||||
if (!*p)
|
||||
p = "/";
|
||||
|
||||
quote_doc:
|
||||
count = 1;
|
||||
for (i = 0; p[i] != '\0'; ++i) {
|
||||
if ((!pre_quoted && p[i] == '%') ||
|
||||
!fetch_urlpath_safe(p[i]))
|
||||
count += 3;
|
||||
else
|
||||
++count;
|
||||
}
|
||||
|
||||
if ((u->doc = malloc(count)) == NULL) {
|
||||
fetch_syserr();
|
||||
goto ouch;
|
||||
}
|
||||
for (i = 0; *p != '\0'; ++p) {
|
||||
if ((!pre_quoted && *p == '%') ||
|
||||
!fetch_urlpath_safe(*p)) {
|
||||
u->doc[i++] = '%';
|
||||
if ((unsigned char)*p < 160)
|
||||
u->doc[i++] = '0' + ((unsigned char)*p) / 16;
|
||||
else
|
||||
u->doc[i++] = 'a' - 10 + ((unsigned char)*p) / 16;
|
||||
if ((unsigned char)*p % 16 < 10)
|
||||
u->doc[i++] = '0' + ((unsigned char)*p) % 16;
|
||||
else
|
||||
u->doc[i++] = 'a' - 10 + ((unsigned char)*p) % 16;
|
||||
} else
|
||||
u->doc[i++] = *p;
|
||||
}
|
||||
u->doc[i] = '\0';
|
||||
|
||||
return (u);
|
||||
|
||||
ouch:
|
||||
free(u);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Free a URL
|
||||
*/
|
||||
void
|
||||
fetchFreeURL(struct url *u)
|
||||
{
|
||||
if (!u) {
|
||||
return;
|
||||
}
|
||||
if (u->doc) {
|
||||
free(u->doc);
|
||||
}
|
||||
free(u);
|
||||
}
|
||||
|
||||
static char
|
||||
xdigit2digit(char digit)
|
||||
{
|
||||
digit = tolower((unsigned char)digit);
|
||||
if (digit >= 'a' && digit <= 'f')
|
||||
digit = digit - 'a' + 10;
|
||||
else
|
||||
digit = digit - '0';
|
||||
|
||||
return digit;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unquote whole URL.
|
||||
* Skips optional parts like query or fragment identifier.
|
||||
*/
|
||||
char *
|
||||
fetchUnquotePath(struct url *url)
|
||||
{
|
||||
char *unquoted;
|
||||
const char *iter;
|
||||
size_t i;
|
||||
|
||||
if ((unquoted = malloc(strlen(url->doc) + 1)) == NULL)
|
||||
return NULL;
|
||||
|
||||
for (i = 0, iter = url->doc; *iter != '\0'; ++iter) {
|
||||
if (*iter == '#' || *iter == '?')
|
||||
break;
|
||||
if (iter[0] != '%' ||
|
||||
!isxdigit((unsigned char)iter[1]) ||
|
||||
!isxdigit((unsigned char)iter[2])) {
|
||||
unquoted[i++] = *iter;
|
||||
continue;
|
||||
}
|
||||
unquoted[i++] = xdigit2digit(iter[1]) * 16 +
|
||||
xdigit2digit(iter[2]);
|
||||
iter += 2;
|
||||
}
|
||||
unquoted[i] = '\0';
|
||||
return unquoted;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Extract the file name component of a URL.
|
||||
*/
|
||||
char *
|
||||
fetchUnquoteFilename(struct url *url)
|
||||
{
|
||||
char *unquoted, *filename;
|
||||
const char *last_slash;
|
||||
|
||||
if ((unquoted = fetchUnquotePath(url)) == NULL)
|
||||
return NULL;
|
||||
|
||||
if ((last_slash = strrchr(unquoted, '/')) == NULL)
|
||||
return unquoted;
|
||||
filename = strdup(last_slash + 1);
|
||||
free(unquoted);
|
||||
return filename;
|
||||
}
|
||||
|
||||
char *
|
||||
fetchStringifyURL(const struct url *url)
|
||||
{
|
||||
size_t total;
|
||||
char *doc;
|
||||
|
||||
/* scheme :// user : pwd @ host :port doc */
|
||||
total = strlen(url->scheme) + 3 + strlen(url->user) + 1 +
|
||||
strlen(url->pwd) + 1 + strlen(url->host) + 6 + strlen(url->doc) + 1;
|
||||
if ((doc = malloc(total)) == NULL)
|
||||
return NULL;
|
||||
if (url->port != 0)
|
||||
snprintf(doc, total, "%s%s%s%s%s%s%s:%d%s",
|
||||
url->scheme,
|
||||
url->scheme[0] != '\0' ? "://" : "",
|
||||
url->user,
|
||||
url->pwd[0] != '\0' ? ":" : "",
|
||||
url->pwd,
|
||||
url->user[0] != '\0' || url->pwd[0] != '\0' ? "@" : "",
|
||||
url->host,
|
||||
(int)url->port,
|
||||
url->doc);
|
||||
else {
|
||||
snprintf(doc, total, "%s%s%s%s%s%s%s%s",
|
||||
url->scheme,
|
||||
url->scheme[0] != '\0' ? "://" : "",
|
||||
url->user,
|
||||
url->pwd[0] != '\0' ? ":" : "",
|
||||
url->pwd,
|
||||
url->user[0] != '\0' || url->pwd[0] != '\0' ? "@" : "",
|
||||
url->host,
|
||||
url->doc);
|
||||
}
|
||||
return doc;
|
||||
}
|
||||
192
lib/external/fetch/fetch.h
vendored
Normal file
192
lib/external/fetch/fetch.h
vendored
Normal file
@@ -0,0 +1,192 @@
|
||||
/* $NetBSD: fetch.h,v 1.16 2010/01/22 13:21:09 joerg Exp $ */
|
||||
/*-
|
||||
* Copyright (c) 1998-2014 Dag-Erling Smorgrav
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer
|
||||
* in this position and unchanged.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _FETCH_H_INCLUDED
|
||||
#define _FETCH_H_INCLUDED
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define _LIBFETCH_VER "xbps/2.0"
|
||||
|
||||
#define URL_HOSTLEN 255
|
||||
#define URL_SCHEMELEN 16
|
||||
#define URL_USERLEN 256
|
||||
#define URL_PWDLEN 256
|
||||
|
||||
typedef struct fetchIO fetchIO;
|
||||
|
||||
struct url {
|
||||
char scheme[URL_SCHEMELEN + 1];
|
||||
char user[URL_USERLEN + 1];
|
||||
char pwd[URL_PWDLEN + 1];
|
||||
char host[URL_HOSTLEN + 1];
|
||||
int port;
|
||||
char *doc;
|
||||
off_t offset;
|
||||
size_t length;
|
||||
time_t last_modified;
|
||||
};
|
||||
|
||||
struct url_stat {
|
||||
off_t size;
|
||||
time_t atime;
|
||||
time_t mtime;
|
||||
};
|
||||
|
||||
struct url_list {
|
||||
size_t length;
|
||||
size_t alloc_size;
|
||||
struct url *urls;
|
||||
};
|
||||
|
||||
/* Recognized schemes */
|
||||
#define SCHEME_FTP "ftp"
|
||||
#define SCHEME_HTTP "http"
|
||||
#define SCHEME_HTTPS "https"
|
||||
#define SCHEME_FILE "file"
|
||||
#define SCHEME_SOCKS5 "socks5"
|
||||
|
||||
/* Error codes */
|
||||
#define FETCH_ABORT 1
|
||||
#define FETCH_AUTH 2
|
||||
#define FETCH_DOWN 3
|
||||
#define FETCH_EXISTS 4
|
||||
#define FETCH_FULL 5
|
||||
#define FETCH_INFO 6
|
||||
#define FETCH_MEMORY 7
|
||||
#define FETCH_MOVED 8
|
||||
#define FETCH_NETWORK 9
|
||||
#define FETCH_OK 10
|
||||
#define FETCH_PROTO 11
|
||||
#define FETCH_RESOLV 12
|
||||
#define FETCH_SERVER 13
|
||||
#define FETCH_TEMP 14
|
||||
#define FETCH_TIMEOUT 15
|
||||
#define FETCH_UNAVAIL 16
|
||||
#define FETCH_UNKNOWN 17
|
||||
#define FETCH_URL 18
|
||||
#define FETCH_VERBOSE 19
|
||||
#define FETCH_UNCHANGED 20
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void fetchIO_close(fetchIO *);
|
||||
ssize_t fetchIO_read(fetchIO *, void *, size_t);
|
||||
ssize_t fetchIO_write(fetchIO *, const void *, size_t);
|
||||
|
||||
/* fetchIO-specific functions */
|
||||
fetchIO *fetchXGetFile(struct url *, struct url_stat *, const char *);
|
||||
fetchIO *fetchGetFile(struct url *, const char *);
|
||||
fetchIO *fetchPutFile(struct url *, const char *);
|
||||
int fetchStatFile(struct url *, struct url_stat *, const char *);
|
||||
int fetchListFile(struct url_list *, struct url *, const char *,
|
||||
const char *);
|
||||
|
||||
/* HTTP-specific functions */
|
||||
fetchIO *fetchXGetHTTP(struct url *, struct url_stat *, const char *);
|
||||
fetchIO *fetchGetHTTP(struct url *, const char *);
|
||||
fetchIO *fetchPutHTTP(struct url *, const char *);
|
||||
int fetchStatHTTP(struct url *, struct url_stat *, const char *);
|
||||
int fetchListHTTP(struct url_list *, struct url *, const char *,
|
||||
const char *);
|
||||
|
||||
/* FTP-specific functions */
|
||||
fetchIO *fetchXGetFTP(struct url *, struct url_stat *, const char *);
|
||||
fetchIO *fetchGetFTP(struct url *, const char *);
|
||||
fetchIO *fetchPutFTP(struct url *, const char *);
|
||||
int fetchStatFTP(struct url *, struct url_stat *, const char *);
|
||||
int fetchListFTP(struct url_list *, struct url *, const char *,
|
||||
const char *);
|
||||
|
||||
/* Generic functions */
|
||||
fetchIO *fetchXGetURL(const char *, struct url_stat *, const char *);
|
||||
fetchIO *fetchGetURL(const char *, const char *);
|
||||
fetchIO *fetchPutURL(const char *, const char *);
|
||||
int fetchStatURL(const char *, struct url_stat *, const char *);
|
||||
int fetchListURL(struct url_list *, const char *, const char *,
|
||||
const char *);
|
||||
fetchIO *fetchXGet(struct url *, struct url_stat *, const char *);
|
||||
fetchIO *fetchGet(struct url *, const char *);
|
||||
fetchIO *fetchPut(struct url *, const char *);
|
||||
int fetchStat(struct url *, struct url_stat *, const char *);
|
||||
int fetchList(struct url_list *, struct url *, const char *,
|
||||
const char *);
|
||||
|
||||
/* URL parsing */
|
||||
struct url *fetchMakeURL(const char *, const char *, int,
|
||||
const char *, const char *, const char *);
|
||||
struct url *fetchParseURL(const char *);
|
||||
struct url *fetchCopyURL(const struct url *);
|
||||
char *fetchStringifyURL(const struct url *);
|
||||
void fetchFreeURL(struct url *);
|
||||
|
||||
/* URL listening */
|
||||
void fetchInitURLList(struct url_list *);
|
||||
int fetchAppendURLList(struct url_list *, const struct url_list *);
|
||||
void fetchFreeURLList(struct url_list *);
|
||||
char *fetchUnquotePath(struct url *);
|
||||
char *fetchUnquoteFilename(struct url *);
|
||||
|
||||
/* Connection caching */
|
||||
void fetchConnectionCacheInit(int, int);
|
||||
void fetchConnectionCacheClose(void);
|
||||
|
||||
/* Authentication */
|
||||
typedef int (*auth_t)(struct url *);
|
||||
extern auth_t fetchAuthMethod;
|
||||
|
||||
/* Last error code */
|
||||
extern int fetchLastErrCode;
|
||||
#define MAXERRSTRING 256
|
||||
extern char fetchLastErrString[MAXERRSTRING];
|
||||
|
||||
/* I/O timeout */
|
||||
extern int fetchTimeout;
|
||||
|
||||
/* Connect timeout */
|
||||
extern int fetchConnTimeout;
|
||||
|
||||
/* Connect attempt delay */
|
||||
extern int fetchConnDelay;
|
||||
|
||||
/* Restart interrupted syscalls */
|
||||
extern volatile int fetchRestartCalls;
|
||||
|
||||
/* Extra verbosity */
|
||||
extern int fetchDebug;
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
269
lib/external/fetch/file.c
vendored
Normal file
269
lib/external/fetch/file.c
vendored
Normal file
@@ -0,0 +1,269 @@
|
||||
/* $NetBSD: file.c,v 1.15 2009/10/15 12:36:57 joerg Exp $ */
|
||||
/*-
|
||||
* Copyright (c) 1998-2004 Dag-Erling Coïdan Smørav
|
||||
* Copyright (c) 2008, 2009 Joerg Sonnenberger <joerg@NetBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer
|
||||
* in this position and unchanged.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD: file.c,v 1.18 2007/12/14 10:26:58 des Exp $
|
||||
*/
|
||||
|
||||
#include "compat.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <fnmatch.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "fetch.h"
|
||||
#include "common.h"
|
||||
|
||||
static int fetch_stat_file(int, struct url_stat *);
|
||||
|
||||
static ssize_t
|
||||
fetchFile_read(void *cookie, void *buf, size_t len)
|
||||
{
|
||||
return read(*(int *)cookie, buf, len);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
fetchFile_write(void *cookie, const void *buf, size_t len)
|
||||
{
|
||||
return write(*(int *)cookie, buf, len);
|
||||
}
|
||||
|
||||
static void
|
||||
fetchFile_close(void *cookie)
|
||||
{
|
||||
int fd = *(int *)cookie;
|
||||
|
||||
free(cookie);
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
fetchIO *
|
||||
fetchXGetFile(struct url *u, struct url_stat *us, const char *flags)
|
||||
{
|
||||
char *path;
|
||||
fetchIO *f;
|
||||
struct url_stat local_us;
|
||||
int if_modified_since, fd, *cookie;
|
||||
|
||||
if_modified_since = CHECK_FLAG('i');
|
||||
if (if_modified_since && us == NULL)
|
||||
us = &local_us;
|
||||
|
||||
if ((path = fetchUnquotePath(u)) == NULL) {
|
||||
fetch_syserr();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fd = open(path, O_RDONLY);
|
||||
free(path);
|
||||
if (fd == -1) {
|
||||
fetch_syserr();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (us && fetch_stat_file(fd, us) == -1) {
|
||||
close(fd);
|
||||
fetch_syserr();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (if_modified_since && u->last_modified > 0 &&
|
||||
u->last_modified >= us->mtime) {
|
||||
close(fd);
|
||||
fetchLastErrCode = FETCH_UNCHANGED;
|
||||
snprintf(fetchLastErrString, MAXERRSTRING, "Unchanged");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (u->offset && lseek(fd, u->offset, SEEK_SET) == -1) {
|
||||
close(fd);
|
||||
fetch_syserr();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cookie = malloc(sizeof(int));
|
||||
if (cookie == NULL) {
|
||||
close(fd);
|
||||
fetch_syserr();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*cookie = fd;
|
||||
f = fetchIO_unopen(cookie, fetchFile_read, fetchFile_write, fetchFile_close);
|
||||
if (f == NULL) {
|
||||
close(fd);
|
||||
free(cookie);
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
fetchIO *
|
||||
fetchGetFile(struct url *u, const char *flags)
|
||||
{
|
||||
return (fetchXGetFile(u, NULL, flags));
|
||||
}
|
||||
|
||||
fetchIO *
|
||||
fetchPutFile(struct url *u, const char *flags)
|
||||
{
|
||||
char *path;
|
||||
fetchIO *f;
|
||||
int fd, *cookie;
|
||||
|
||||
if ((path = fetchUnquotePath(u)) == NULL) {
|
||||
fetch_syserr();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (CHECK_FLAG('a'))
|
||||
fd = open(path, O_WRONLY | O_APPEND);
|
||||
else
|
||||
fd = open(path, O_WRONLY);
|
||||
|
||||
free(path);
|
||||
|
||||
if (fd == -1) {
|
||||
fetch_syserr();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (u->offset && lseek(fd, u->offset, SEEK_SET) == -1) {
|
||||
close(fd);
|
||||
fetch_syserr();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cookie = malloc(sizeof(int));
|
||||
if (cookie == NULL) {
|
||||
close(fd);
|
||||
fetch_syserr();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*cookie = fd;
|
||||
f = fetchIO_unopen(cookie, fetchFile_read, fetchFile_write, fetchFile_close);
|
||||
if (f == NULL) {
|
||||
close(fd);
|
||||
free(cookie);
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
static int
|
||||
fetch_stat_file(int fd, struct url_stat *us)
|
||||
{
|
||||
struct stat sb;
|
||||
|
||||
us->size = -1;
|
||||
us->atime = us->mtime = 0;
|
||||
if (fstat(fd, &sb) == -1) {
|
||||
fetch_syserr();
|
||||
return (-1);
|
||||
}
|
||||
us->size = sb.st_size;
|
||||
us->atime = sb.st_atime;
|
||||
us->mtime = sb.st_mtime;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
fetchStatFile(struct url *u, struct url_stat *us, const char *flags)
|
||||
{
|
||||
char *path;
|
||||
int fd, rv;
|
||||
|
||||
(void)flags;
|
||||
|
||||
if (us == NULL) {
|
||||
fetch_syserr();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((path = fetchUnquotePath(u)) == NULL) {
|
||||
fetch_syserr();
|
||||
return -1;
|
||||
}
|
||||
|
||||
fd = open(path, O_RDONLY);
|
||||
free(path);
|
||||
|
||||
if (fd == -1) {
|
||||
fetch_syserr();
|
||||
return -1;
|
||||
}
|
||||
|
||||
rv = fetch_stat_file(fd, us);
|
||||
close(fd);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
int
|
||||
fetchListFile(struct url_list *ue, struct url *u, const char *pattern, const char *flags)
|
||||
{
|
||||
char *path;
|
||||
struct dirent *de;
|
||||
DIR *dir;
|
||||
int ret;
|
||||
|
||||
(void)flags;
|
||||
|
||||
if ((path = fetchUnquotePath(u)) == NULL) {
|
||||
fetch_syserr();
|
||||
return -1;
|
||||
}
|
||||
|
||||
dir = opendir(path);
|
||||
free(path);
|
||||
|
||||
if (dir == NULL) {
|
||||
fetch_syserr();
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
while ((de = readdir(dir)) != NULL) {
|
||||
if (pattern && fnmatch(pattern, de->d_name, 0) != 0)
|
||||
continue;
|
||||
ret = fetch_add_entry(ue, u, de->d_name, 0);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
|
||||
return ret;
|
||||
}
|
||||
1295
lib/external/fetch/ftp.c
vendored
Normal file
1295
lib/external/fetch/ftp.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
48
lib/external/fetch/ftp.errors
vendored
Normal file
48
lib/external/fetch/ftp.errors
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
# $NetBSD: ftp.errors,v 1.2 2008/10/06 12:58:29 joerg Exp $
|
||||
# $FreeBSD: ftp.errors,v 1.6 2002/10/30 06:06:16 des Exp $
|
||||
#
|
||||
# This list is taken from RFC 959.
|
||||
# It probably needs a going over.
|
||||
#
|
||||
110 OK Restart marker reply
|
||||
120 TEMP Service ready in a few minutes
|
||||
125 OK Data connection already open; transfer starting
|
||||
150 OK File status okay; about to open data connection
|
||||
200 OK Command okay
|
||||
202 PROTO Command not implemented, superfluous at this site
|
||||
211 INFO System status, or system help reply
|
||||
212 INFO Directory status
|
||||
213 INFO File status
|
||||
214 INFO Help message
|
||||
215 INFO Set system type
|
||||
220 OK Service ready for new user
|
||||
221 OK Service closing control connection
|
||||
225 OK Data connection open; no transfer in progress
|
||||
226 OK Requested file action successful
|
||||
227 OK Entering Passive Mode
|
||||
229 OK Entering Extended Passive Mode
|
||||
230 OK User logged in, proceed
|
||||
250 OK Requested file action okay, completed
|
||||
257 OK File/directory created
|
||||
331 AUTH User name okay, need password
|
||||
332 AUTH Need account for login
|
||||
350 OK Requested file action pending further information
|
||||
421 DOWN Service not available, closing control connection
|
||||
425 NETWORK Can't open data connection
|
||||
426 ABORT Connection closed; transfer aborted
|
||||
450 UNAVAIL File unavailable (e.g., file busy)
|
||||
451 SERVER Requested action aborted: local error in processing
|
||||
452 FULL Insufficient storage space in system
|
||||
500 PROTO Syntax error, command unrecognized
|
||||
501 PROTO Syntax error in parameters or arguments
|
||||
502 PROTO Command not implemented
|
||||
503 PROTO Bad sequence of commands
|
||||
504 PROTO Command not implemented for that parameter
|
||||
530 AUTH Not logged in
|
||||
532 AUTH Need account for storing files
|
||||
535 PROTO Bug in MediaHawk Video Kernel FTP server
|
||||
550 UNAVAIL File unavailable (e.g., file not found, no access)
|
||||
551 PROTO Requested action aborted. Page type unknown
|
||||
552 FULL Exceeded storage allocation
|
||||
553 EXISTS File name not allowed
|
||||
999 PROTO Protocol error
|
||||
1578
lib/external/fetch/http.c
vendored
Normal file
1578
lib/external/fetch/http.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
46
lib/external/fetch/http.errors
vendored
Normal file
46
lib/external/fetch/http.errors
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
# $FreeBSD$ revision 241840
|
||||
#
|
||||
# This list is taken from RFC 2068.
|
||||
#
|
||||
100 OK Continue
|
||||
101 OK Switching Protocols
|
||||
200 OK OK
|
||||
201 OK Created
|
||||
202 OK Accepted
|
||||
203 INFO Non-Authoritative Information
|
||||
204 OK No Content
|
||||
205 OK Reset Content
|
||||
206 OK Partial Content
|
||||
300 MOVED Multiple Choices
|
||||
301 MOVED Moved Permanently
|
||||
302 MOVED Moved Temporarily
|
||||
303 MOVED See Other
|
||||
304 UNCHANGED Not Modified
|
||||
305 INFO Use Proxy
|
||||
307 MOVED Temporary Redirect
|
||||
308 MOVED Permanent Redirect
|
||||
400 PROTO Bad Request
|
||||
401 AUTH Unauthorized
|
||||
402 AUTH Payment Required
|
||||
403 AUTH Forbidden
|
||||
404 UNAVAIL Not Found
|
||||
405 PROTO Method Not Allowed
|
||||
406 PROTO Not Acceptable
|
||||
407 AUTH Proxy Authentication Required
|
||||
408 TIMEOUT Request Time-out
|
||||
409 EXISTS Conflict
|
||||
410 UNAVAIL Gone
|
||||
411 PROTO Length Required
|
||||
412 SERVER Precondition Failed
|
||||
413 PROTO Request Entity Too Large
|
||||
414 PROTO Request-URI Too Large
|
||||
415 PROTO Unsupported Media Type
|
||||
416 UNAVAIL Requested Range Not Satisfiable
|
||||
417 SERVER Expectation Failed
|
||||
500 SERVER Internal Server Error
|
||||
501 PROTO Not Implemented
|
||||
502 SERVER Bad Gateway
|
||||
503 TEMP Service Unavailable
|
||||
504 TIMEOUT Gateway Time-out
|
||||
505 PROTO HTTP Version not supported
|
||||
999 PROTO Protocol error
|
||||
144
lib/external/humanize_number.c
vendored
Normal file
144
lib/external/humanize_number.c
vendored
Normal file
@@ -0,0 +1,144 @@
|
||||
/* $NetBSD: humanize_number.c,v 1.14 2008/04/28 20:22:59 martin Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997, 1998, 1999, 2002 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
|
||||
* NASA Ames Research Center, by Luke Mewburn and by Tomas Svensson.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <locale.h>
|
||||
|
||||
#include "xbps_api_impl.h"
|
||||
#include "compat.h"
|
||||
|
||||
int HIDDEN
|
||||
humanize_number(char *buf, size_t len, int64_t bytes,
|
||||
const char *suffix, int scale, int flags)
|
||||
{
|
||||
const char *prefixes, *sep;
|
||||
int b, i, r, maxscale, s1, s2, sign;
|
||||
int64_t divisor, max;
|
||||
size_t baselen;
|
||||
|
||||
assert(buf != NULL);
|
||||
assert(suffix != NULL);
|
||||
assert(scale >= 0);
|
||||
|
||||
if (flags & HN_DIVISOR_1000) {
|
||||
/* SI for decimal multiplies */
|
||||
divisor = 1000;
|
||||
if (flags & HN_B)
|
||||
prefixes = "B\0k\0M\0G\0T\0P\0E";
|
||||
else
|
||||
prefixes = "\0\0k\0M\0G\0T\0P\0E";
|
||||
} else {
|
||||
/*
|
||||
* binary multiplies
|
||||
* XXX IEC 60027-2 recommends Ki, Mi, Gi...
|
||||
*/
|
||||
divisor = 1024;
|
||||
if (flags & HN_B)
|
||||
prefixes = "B\0K\0M\0G\0T\0P\0E";
|
||||
else
|
||||
prefixes = "\0\0K\0M\0G\0T\0P\0E";
|
||||
}
|
||||
|
||||
#define SCALE2PREFIX(scale) (&prefixes[(scale) << 1])
|
||||
maxscale = 7;
|
||||
|
||||
if (scale >= maxscale &&
|
||||
(scale & (HN_AUTOSCALE | HN_GETSCALE)) == 0)
|
||||
return (-1);
|
||||
|
||||
if (buf == NULL || suffix == NULL)
|
||||
return (-1);
|
||||
|
||||
if (len > 0)
|
||||
buf[0] = '\0';
|
||||
if (bytes < 0) {
|
||||
sign = -1;
|
||||
bytes *= -100;
|
||||
baselen = 3; /* sign, digit, prefix */
|
||||
} else {
|
||||
sign = 1;
|
||||
bytes *= 100;
|
||||
baselen = 2; /* digit, prefix */
|
||||
}
|
||||
if (flags & HN_NOSPACE)
|
||||
sep = "";
|
||||
else {
|
||||
sep = " ";
|
||||
baselen++;
|
||||
}
|
||||
baselen += strlen(suffix);
|
||||
|
||||
/* Check if enough room for `x y' + suffix + `\0' */
|
||||
if (len < baselen + 1)
|
||||
return (-1);
|
||||
|
||||
if (scale & (HN_AUTOSCALE | HN_GETSCALE)) {
|
||||
/* See if there is additional columns can be used. */
|
||||
for (max = 100, i = (int)(len - baselen); i-- > 0;)
|
||||
max *= 10;
|
||||
|
||||
/*
|
||||
* Divide the number until it fits the given column.
|
||||
* If there will be an overflow by the rounding below,
|
||||
* divide once more.
|
||||
*/
|
||||
for (i = 0; bytes >= max - 50 && i < maxscale; i++)
|
||||
bytes /= divisor;
|
||||
|
||||
if (scale & HN_GETSCALE)
|
||||
return (i);
|
||||
} else
|
||||
for (i = 0; i < scale && i < maxscale; i++)
|
||||
bytes /= divisor;
|
||||
|
||||
/* If a value <= 9.9 after rounding and ... */
|
||||
if (bytes < 995 && i > 0 && flags & HN_DECIMAL) {
|
||||
/* baselen + \0 + .N */
|
||||
if (len < baselen + 1 + 2)
|
||||
return (-1);
|
||||
b = ((int)bytes + 5) / 10;
|
||||
s1 = b / 10;
|
||||
s2 = b % 10;
|
||||
r = snprintf(buf, len, "%d%s%d%s%s%s",
|
||||
sign * s1, localeconv()->decimal_point, s2,
|
||||
sep, SCALE2PREFIX(i), suffix);
|
||||
} else
|
||||
r = snprintf(buf, len, "%" PRId64 "%s%s%s",
|
||||
sign * ((bytes + 50) / 100),
|
||||
sep, SCALE2PREFIX(i), suffix);
|
||||
|
||||
return (r);
|
||||
}
|
||||
152
lib/external/portableproplib/prop/prop_array.h
vendored
Normal file
152
lib/external/portableproplib/prop/prop_array.h
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
/* $NetBSD: prop_array.h,v 1.8 2008/09/11 13:15:13 haad Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2014 Juan Romero Pardines.
|
||||
* Copyright (c) 2006 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Jason R. Thorpe.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _PROPLIB_PROP_ARRAY_H_
|
||||
#define _PROPLIB_PROP_ARRAY_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <prop/prop_object.h>
|
||||
|
||||
typedef struct _prop_array *prop_array_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
prop_array_t prop_array_create(void);
|
||||
prop_array_t prop_array_create_with_capacity(unsigned int);
|
||||
|
||||
prop_array_t prop_array_copy(prop_array_t);
|
||||
prop_array_t prop_array_copy_mutable(prop_array_t);
|
||||
|
||||
unsigned int prop_array_capacity(prop_array_t);
|
||||
unsigned int prop_array_count(prop_array_t);
|
||||
bool prop_array_ensure_capacity(prop_array_t, unsigned int);
|
||||
|
||||
void prop_array_make_immutable(prop_array_t);
|
||||
bool prop_array_mutable(prop_array_t);
|
||||
|
||||
prop_object_iterator_t prop_array_iterator(prop_array_t);
|
||||
|
||||
prop_object_t prop_array_get(prop_array_t, unsigned int);
|
||||
bool prop_array_set(prop_array_t, unsigned int, prop_object_t);
|
||||
bool prop_array_add(prop_array_t, prop_object_t);
|
||||
bool prop_array_add_first(prop_array_t, prop_object_t);
|
||||
void prop_array_remove(prop_array_t, unsigned int);
|
||||
|
||||
bool prop_array_equals(prop_array_t, prop_array_t);
|
||||
|
||||
char * prop_array_externalize(prop_array_t);
|
||||
prop_array_t prop_array_internalize(const char *);
|
||||
|
||||
bool prop_array_externalize_to_file(prop_array_t, const char *);
|
||||
bool prop_array_externalize_to_zfile(prop_array_t, const char *);
|
||||
prop_array_t prop_array_internalize_from_file(const char *);
|
||||
prop_array_t prop_array_internalize_from_zfile(const char *);
|
||||
|
||||
/*
|
||||
* Utility routines to make it more convenient to work with values
|
||||
* stored in dictionaries.
|
||||
*/
|
||||
bool prop_array_get_bool(prop_array_t, unsigned int,
|
||||
bool *);
|
||||
bool prop_array_set_bool(prop_array_t, unsigned int,
|
||||
bool);
|
||||
|
||||
bool prop_array_get_int8(prop_array_t, unsigned int,
|
||||
int8_t *);
|
||||
bool prop_array_get_uint8(prop_array_t, unsigned int,
|
||||
uint8_t *);
|
||||
bool prop_array_set_int8(prop_array_t, unsigned int,
|
||||
int8_t);
|
||||
bool prop_array_set_uint8(prop_array_t, unsigned int,
|
||||
uint8_t);
|
||||
|
||||
bool prop_array_get_int16(prop_array_t, unsigned int,
|
||||
int16_t *);
|
||||
bool prop_array_get_uint16(prop_array_t, unsigned int,
|
||||
uint16_t *);
|
||||
bool prop_array_set_int16(prop_array_t, unsigned int,
|
||||
int16_t);
|
||||
bool prop_array_set_uint16(prop_array_t, unsigned int,
|
||||
uint16_t);
|
||||
|
||||
bool prop_array_get_int32(prop_array_t, unsigned int,
|
||||
int32_t *);
|
||||
bool prop_array_get_uint32(prop_array_t, unsigned int,
|
||||
uint32_t *);
|
||||
bool prop_array_set_int32(prop_array_t, unsigned int,
|
||||
int32_t);
|
||||
bool prop_array_set_uint32(prop_array_t, unsigned int,
|
||||
uint32_t);
|
||||
|
||||
bool prop_array_get_int64(prop_array_t, unsigned int,
|
||||
int64_t *);
|
||||
bool prop_array_get_uint64(prop_array_t, unsigned int,
|
||||
uint64_t *);
|
||||
bool prop_array_set_int64(prop_array_t, unsigned int,
|
||||
int64_t);
|
||||
bool prop_array_set_uint64(prop_array_t, unsigned int,
|
||||
uint64_t);
|
||||
|
||||
bool prop_array_add_int8(prop_array_t, int8_t);
|
||||
bool prop_array_add_uint8(prop_array_t, uint8_t);
|
||||
|
||||
bool prop_array_add_int16(prop_array_t, int16_t);
|
||||
bool prop_array_add_uint16(prop_array_t, uint16_t);
|
||||
|
||||
bool prop_array_add_int32(prop_array_t, int32_t);
|
||||
bool prop_array_add_uint32(prop_array_t, uint32_t);
|
||||
|
||||
bool prop_array_add_int64(prop_array_t, int64_t);
|
||||
bool prop_array_add_uint64(prop_array_t, uint64_t);
|
||||
|
||||
bool prop_array_get_cstring(prop_array_t, unsigned int,
|
||||
char **);
|
||||
bool prop_array_set_cstring(prop_array_t, unsigned int,
|
||||
const char *);
|
||||
bool prop_array_add_cstring(prop_array_t, const char *);
|
||||
bool prop_array_add_cstring_nocopy(prop_array_t,
|
||||
const char *);
|
||||
bool prop_array_get_cstring_nocopy(prop_array_t,
|
||||
unsigned int,
|
||||
const char **);
|
||||
bool prop_array_set_cstring_nocopy(prop_array_t,
|
||||
unsigned int,
|
||||
const char *);
|
||||
bool prop_array_add_and_rel(prop_array_t, prop_object_t);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _PROPLIB_PROP_ARRAY_H_ */
|
||||
55
lib/external/portableproplib/prop/prop_bool.h
vendored
Normal file
55
lib/external/portableproplib/prop/prop_bool.h
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
/* $NetBSD: prop_bool.h,v 1.4 2008/04/28 20:22:51 martin Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2006 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Jason R. Thorpe.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _PROPLIB_PROP_BOOL_H_
|
||||
#define _PROPLIB_PROP_BOOL_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <prop/prop_object.h>
|
||||
|
||||
typedef struct _prop_bool *prop_bool_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
prop_bool_t prop_bool_create(bool);
|
||||
prop_bool_t prop_bool_copy(prop_bool_t);
|
||||
|
||||
bool prop_bool_true(prop_bool_t);
|
||||
|
||||
bool prop_bool_equals(prop_bool_t, prop_bool_t);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _PROPLIB_PROP_BOOL_H_ */
|
||||
62
lib/external/portableproplib/prop/prop_data.h
vendored
Normal file
62
lib/external/portableproplib/prop/prop_data.h
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
/* $NetBSD: prop_data.h,v 1.3 2008/04/28 20:22:51 martin Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2006 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Jason R. Thorpe.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _PROPLIB_PROP_DATA_H_
|
||||
#define _PROPLIB_PROP_DATA_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <prop/prop_object.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
typedef struct _prop_data *prop_data_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
prop_data_t prop_data_create_data(const void *, size_t);
|
||||
prop_data_t prop_data_create_data_nocopy(const void *, size_t);
|
||||
|
||||
prop_data_t prop_data_copy(prop_data_t);
|
||||
|
||||
size_t prop_data_size(prop_data_t);
|
||||
|
||||
void * prop_data_data(prop_data_t);
|
||||
const void * prop_data_data_nocopy(prop_data_t);
|
||||
|
||||
bool prop_data_equals(prop_data_t, prop_data_t);
|
||||
bool prop_data_equals_data(prop_data_t, const void *, size_t);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _PROPLIB_PROP_DATA_H_ */
|
||||
158
lib/external/portableproplib/prop/prop_dictionary.h
vendored
Normal file
158
lib/external/portableproplib/prop/prop_dictionary.h
vendored
Normal file
@@ -0,0 +1,158 @@
|
||||
/* $NetBSD: prop_dictionary.h,v 1.9 2008/04/28 20:22:51 martin Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2006 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Jason R. Thorpe.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _PROPLIB_PROP_DICTIONARY_H_
|
||||
#define _PROPLIB_PROP_DICTIONARY_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <prop/prop_object.h>
|
||||
#include <prop/prop_array.h>
|
||||
|
||||
typedef struct _prop_dictionary *prop_dictionary_t;
|
||||
typedef struct _prop_dictionary_keysym *prop_dictionary_keysym_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
prop_dictionary_t prop_dictionary_create(void);
|
||||
prop_dictionary_t prop_dictionary_create_with_capacity(unsigned int);
|
||||
|
||||
prop_dictionary_t prop_dictionary_copy(prop_dictionary_t);
|
||||
prop_dictionary_t prop_dictionary_copy_mutable(prop_dictionary_t);
|
||||
|
||||
unsigned int prop_dictionary_count(prop_dictionary_t);
|
||||
bool prop_dictionary_ensure_capacity(prop_dictionary_t,
|
||||
unsigned int);
|
||||
|
||||
void prop_dictionary_make_immutable(prop_dictionary_t);
|
||||
bool prop_dictionary_mutable(prop_dictionary_t);
|
||||
|
||||
prop_object_iterator_t prop_dictionary_iterator(prop_dictionary_t);
|
||||
prop_array_t prop_dictionary_all_keys(prop_dictionary_t);
|
||||
|
||||
prop_object_t prop_dictionary_get(prop_dictionary_t, const char *);
|
||||
bool prop_dictionary_set(prop_dictionary_t, const char *,
|
||||
prop_object_t);
|
||||
void prop_dictionary_remove(prop_dictionary_t, const char *);
|
||||
|
||||
prop_object_t prop_dictionary_get_keysym(prop_dictionary_t,
|
||||
prop_dictionary_keysym_t);
|
||||
bool prop_dictionary_set_keysym(prop_dictionary_t,
|
||||
prop_dictionary_keysym_t,
|
||||
prop_object_t);
|
||||
void prop_dictionary_remove_keysym(prop_dictionary_t,
|
||||
prop_dictionary_keysym_t);
|
||||
|
||||
bool prop_dictionary_equals(prop_dictionary_t, prop_dictionary_t);
|
||||
|
||||
char * prop_dictionary_externalize(prop_dictionary_t);
|
||||
prop_dictionary_t prop_dictionary_internalize(const char *);
|
||||
|
||||
bool prop_dictionary_externalize_to_file(prop_dictionary_t,
|
||||
const char *);
|
||||
bool prop_dictionary_externalize_to_zfile(prop_dictionary_t,
|
||||
const char *);
|
||||
prop_dictionary_t prop_dictionary_internalize_from_file(const char *);
|
||||
prop_dictionary_t prop_dictionary_internalize_from_zfile(const char *);
|
||||
|
||||
const char * prop_dictionary_keysym_cstring_nocopy(prop_dictionary_keysym_t);
|
||||
|
||||
bool prop_dictionary_keysym_equals(prop_dictionary_keysym_t,
|
||||
prop_dictionary_keysym_t);
|
||||
|
||||
/*
|
||||
* Utility routines to make it more convenient to work with values
|
||||
* stored in dictionaries.
|
||||
*/
|
||||
bool prop_dictionary_get_dict(prop_dictionary_t, const char *,
|
||||
prop_dictionary_t *);
|
||||
bool prop_dictionary_get_bool(prop_dictionary_t, const char *,
|
||||
bool *);
|
||||
bool prop_dictionary_set_bool(prop_dictionary_t, const char *,
|
||||
bool);
|
||||
|
||||
bool prop_dictionary_get_int8(prop_dictionary_t, const char *,
|
||||
int8_t *);
|
||||
bool prop_dictionary_get_uint8(prop_dictionary_t, const char *,
|
||||
uint8_t *);
|
||||
bool prop_dictionary_set_int8(prop_dictionary_t, const char *,
|
||||
int8_t);
|
||||
bool prop_dictionary_set_uint8(prop_dictionary_t, const char *,
|
||||
uint8_t);
|
||||
|
||||
bool prop_dictionary_get_int16(prop_dictionary_t, const char *,
|
||||
int16_t *);
|
||||
bool prop_dictionary_get_uint16(prop_dictionary_t, const char *,
|
||||
uint16_t *);
|
||||
bool prop_dictionary_set_int16(prop_dictionary_t, const char *,
|
||||
int16_t);
|
||||
bool prop_dictionary_set_uint16(prop_dictionary_t, const char *,
|
||||
uint16_t);
|
||||
|
||||
bool prop_dictionary_get_int32(prop_dictionary_t, const char *,
|
||||
int32_t *);
|
||||
bool prop_dictionary_get_uint32(prop_dictionary_t, const char *,
|
||||
uint32_t *);
|
||||
bool prop_dictionary_set_int32(prop_dictionary_t, const char *,
|
||||
int32_t);
|
||||
bool prop_dictionary_set_uint32(prop_dictionary_t, const char *,
|
||||
uint32_t);
|
||||
|
||||
bool prop_dictionary_get_int64(prop_dictionary_t, const char *,
|
||||
int64_t *);
|
||||
bool prop_dictionary_get_uint64(prop_dictionary_t, const char *,
|
||||
uint64_t *);
|
||||
bool prop_dictionary_set_int64(prop_dictionary_t, const char *,
|
||||
int64_t);
|
||||
bool prop_dictionary_set_uint64(prop_dictionary_t, const char *,
|
||||
uint64_t);
|
||||
|
||||
bool prop_dictionary_get_cstring(prop_dictionary_t, const char *,
|
||||
char **);
|
||||
bool prop_dictionary_set_cstring(prop_dictionary_t, const char *,
|
||||
const char *);
|
||||
|
||||
bool prop_dictionary_get_cstring_nocopy(prop_dictionary_t,
|
||||
const char *,
|
||||
const char **);
|
||||
bool prop_dictionary_set_cstring_nocopy(prop_dictionary_t,
|
||||
const char *,
|
||||
const char *);
|
||||
bool prop_dictionary_set_and_rel(prop_dictionary_t,
|
||||
const char *,
|
||||
prop_object_t);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _PROPLIB_PROP_DICTIONARY_H_ */
|
||||
96
lib/external/portableproplib/prop/prop_ingest.h
vendored
Normal file
96
lib/external/portableproplib/prop/prop_ingest.h
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
/* $NetBSD: prop_ingest.h,v 1.3 2008/04/28 20:22:51 martin Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2006 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Jason R. Thorpe.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _PROPLIB_PROP_INGEST_H_
|
||||
#define _PROPLIB_PROP_INGEST_H_
|
||||
|
||||
#include <prop/prop_object.h>
|
||||
#include <prop/prop_dictionary.h>
|
||||
|
||||
typedef enum {
|
||||
PROP_INGEST_ERROR_NO_ERROR = 0,
|
||||
PROP_INGEST_ERROR_NO_KEY = 1,
|
||||
PROP_INGEST_ERROR_WRONG_TYPE = 2,
|
||||
PROP_INGEST_ERROR_HANDLER_FAILED = 3
|
||||
} prop_ingest_error_t;
|
||||
|
||||
typedef enum {
|
||||
PROP_INGEST_FLAG_OPTIONAL = 0x01
|
||||
} prop_ingest_flag_t;
|
||||
|
||||
typedef struct _prop_ingest_context *prop_ingest_context_t;
|
||||
|
||||
typedef bool (*prop_ingest_handler_t)(prop_ingest_context_t, prop_object_t);
|
||||
|
||||
typedef struct {
|
||||
const char *pite_key;
|
||||
prop_type_t pite_type;
|
||||
unsigned int pite_flags;
|
||||
prop_ingest_handler_t pite_handler;
|
||||
} prop_ingest_table_entry;
|
||||
|
||||
#define PROP_INGEST(key_, type_, handler_) \
|
||||
{ .pite_key = key_ , \
|
||||
.pite_type = type_ , \
|
||||
.pite_flags = 0 , \
|
||||
.pite_handler = handler_ }
|
||||
|
||||
#define PROP_INGEST_OPTIONAL(key_, type_, handler_) \
|
||||
{ .pite_key = key_ , \
|
||||
.pite_type = type_ , \
|
||||
.pite_flags = PROP_INGEST_FLAG_OPTIONAL , \
|
||||
.pite_handler = handler_ }
|
||||
|
||||
#define PROP_INGEST_END \
|
||||
{ .pite_key = NULL }
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
prop_ingest_context_t
|
||||
prop_ingest_context_alloc(void *);
|
||||
void prop_ingest_context_free(prop_ingest_context_t);
|
||||
|
||||
prop_ingest_error_t
|
||||
prop_ingest_context_error(prop_ingest_context_t);
|
||||
prop_type_t prop_ingest_context_type(prop_ingest_context_t);
|
||||
const char * prop_ingest_context_key(prop_ingest_context_t);
|
||||
void * prop_ingest_context_private(prop_ingest_context_t);
|
||||
|
||||
bool prop_dictionary_ingest(prop_dictionary_t,
|
||||
const prop_ingest_table_entry[],
|
||||
prop_ingest_context_t);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _PROPLIB_PROP_INGEST_H_ */
|
||||
63
lib/external/portableproplib/prop/prop_number.h
vendored
Normal file
63
lib/external/portableproplib/prop/prop_number.h
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
/* $NetBSD: prop_number.h,v 1.6 2008/04/28 20:22:51 martin Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2006 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Jason R. Thorpe.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _PROPLIB_PROP_NUMBER_H_
|
||||
#define _PROPLIB_PROP_NUMBER_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <prop/prop_object.h>
|
||||
|
||||
typedef struct _prop_number *prop_number_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
prop_number_t prop_number_create_integer(int64_t);
|
||||
prop_number_t prop_number_create_unsigned_integer(uint64_t);
|
||||
|
||||
prop_number_t prop_number_copy(prop_number_t);
|
||||
|
||||
int prop_number_size(prop_number_t);
|
||||
bool prop_number_unsigned(prop_number_t);
|
||||
|
||||
int64_t prop_number_integer_value(prop_number_t);
|
||||
uint64_t prop_number_unsigned_integer_value(prop_number_t);
|
||||
|
||||
bool prop_number_equals(prop_number_t, prop_number_t);
|
||||
bool prop_number_equals_integer(prop_number_t, int64_t);
|
||||
bool prop_number_equals_unsigned_integer(prop_number_t, uint64_t);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _PROPLIB_PROP_NUMBER_H_ */
|
||||
73
lib/external/portableproplib/prop/prop_object.h
vendored
Normal file
73
lib/external/portableproplib/prop/prop_object.h
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
/* $NetBSD: prop_object.h,v 1.7 2008/04/28 20:22:51 martin Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2006 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Jason R. Thorpe.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _PROPLIB_PROP_OBJECT_H_
|
||||
#define _PROPLIB_PROP_OBJECT_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef void *prop_object_t;
|
||||
|
||||
typedef enum {
|
||||
PROP_TYPE_UNKNOWN = 0x00000000,
|
||||
PROP_TYPE_BOOL = 0x626f6f6c, /* 'bool' */
|
||||
PROP_TYPE_NUMBER = 0x6e6d6272, /* 'nmbr' */
|
||||
PROP_TYPE_STRING = 0x73746e67, /* 'stng' */
|
||||
PROP_TYPE_DATA = 0x64617461, /* 'data' */
|
||||
PROP_TYPE_ARRAY = 0x61726179, /* 'aray' */
|
||||
PROP_TYPE_DICTIONARY = 0x64696374, /* 'dict' */
|
||||
PROP_TYPE_DICT_KEYSYM = 0x646b6579 /* 'dkey' */
|
||||
} prop_type_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void prop_object_retain(prop_object_t);
|
||||
void prop_object_release(prop_object_t);
|
||||
|
||||
prop_type_t prop_object_type(prop_object_t);
|
||||
|
||||
bool prop_object_equals(prop_object_t, prop_object_t);
|
||||
bool prop_object_equals_with_error(prop_object_t, prop_object_t, bool *);
|
||||
|
||||
typedef struct _prop_object_iterator *prop_object_iterator_t;
|
||||
|
||||
prop_object_t prop_object_iterator_next(prop_object_iterator_t);
|
||||
void prop_object_iterator_reset(prop_object_iterator_t);
|
||||
void prop_object_iterator_release(prop_object_iterator_t);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _PROPLIB_PROP_OBJECT_H_ */
|
||||
68
lib/external/portableproplib/prop/prop_string.h
vendored
Normal file
68
lib/external/portableproplib/prop/prop_string.h
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
/* $NetBSD: prop_string.h,v 1.3 2008/04/28 20:22:51 martin Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2006 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Jason R. Thorpe.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _PROPLIB_PROP_STRING_H_
|
||||
#define _PROPLIB_PROP_STRING_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <prop/prop_object.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
typedef struct _prop_string *prop_string_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
prop_string_t prop_string_create(void);
|
||||
prop_string_t prop_string_create_cstring(const char *);
|
||||
prop_string_t prop_string_create_cstring_nocopy(const char *);
|
||||
|
||||
prop_string_t prop_string_copy(prop_string_t);
|
||||
prop_string_t prop_string_copy_mutable(prop_string_t);
|
||||
|
||||
size_t prop_string_size(prop_string_t);
|
||||
bool prop_string_mutable(prop_string_t);
|
||||
|
||||
char * prop_string_cstring(prop_string_t);
|
||||
const char * prop_string_cstring_nocopy(prop_string_t);
|
||||
|
||||
bool prop_string_append(prop_string_t, prop_string_t);
|
||||
bool prop_string_append_cstring(prop_string_t, const char *);
|
||||
|
||||
bool prop_string_equals(prop_string_t, prop_string_t);
|
||||
bool prop_string_equals_cstring(prop_string_t, const char *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _PROPLIB_PROP_STRING_H_ */
|
||||
45
lib/external/portableproplib/prop/proplib.h
vendored
Normal file
45
lib/external/portableproplib/prop/proplib.h
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
/* $NetBSD: proplib.h,v 1.6 2008/04/28 20:22:51 martin Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2006 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Jason R. Thorpe.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _PROPLIB_PROPLIB_H_
|
||||
#define _PROPLIB_PROPLIB_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <prop/prop_array.h>
|
||||
#include <prop/prop_bool.h>
|
||||
#include <prop/prop_data.h>
|
||||
#include <prop/prop_dictionary.h>
|
||||
#include <prop/prop_number.h>
|
||||
#include <prop/prop_string.h>
|
||||
#include <prop/prop_ingest.h>
|
||||
|
||||
#endif /* _PROPLIB_PROPLIB_H_ */
|
||||
222
lib/external/portableproplib/prop/rbtree.h
vendored
Normal file
222
lib/external/portableproplib/prop/rbtree.h
vendored
Normal file
@@ -0,0 +1,222 @@
|
||||
/* $NetBSD: rbtree.h,v 1.1 2010/09/25 01:42:40 matt Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2001 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Matt Thomas <matt@3am-software.com>.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SYS_RBTREE_H_
|
||||
#define _SYS_RBTREE_H_
|
||||
|
||||
#if defined(_KERNEL) || defined(_STANDALONE)
|
||||
#include <sys/types.h>
|
||||
|
||||
#else
|
||||
#include <stdbool.h>
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
#include <queue.h>
|
||||
|
||||
/* GCC version checking borrowed from glibc. */
|
||||
#if defined(__GNUC__) && defined(__GNUC_MINOR__)
|
||||
# define __GNUC_PREREQ(maj,min) \
|
||||
((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
|
||||
#else
|
||||
# define __GNUC_PREREQ(maj,min) 0
|
||||
#endif
|
||||
|
||||
#if __GNUC_PREREQ(2, 96)
|
||||
# ifndef __predict_true
|
||||
# define __predict_true(exp) __builtin_expect((exp), 1)
|
||||
# endif
|
||||
# ifndef __predict_false
|
||||
# define __predict_false(exp) __builtin_expect((exp), 0)
|
||||
# endif
|
||||
#else
|
||||
# ifndef __predict_true
|
||||
# define __predict_true(exp) (exp)
|
||||
# endif
|
||||
# ifndef __predict_false
|
||||
# define __predict_false(exp) (exp)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct rb_node {
|
||||
struct rb_node *rb_nodes[2];
|
||||
#define RB_DIR_LEFT 0
|
||||
#define RB_DIR_RIGHT 1
|
||||
#define RB_DIR_OTHER 1
|
||||
#define rb_left rb_nodes[RB_DIR_LEFT]
|
||||
#define rb_right rb_nodes[RB_DIR_RIGHT]
|
||||
|
||||
/*
|
||||
* rb_info contains the two flags and the parent back pointer.
|
||||
* We put the two flags in the low two bits since we know that
|
||||
* rb_node will have an alignment of 4 or 8 bytes.
|
||||
*/
|
||||
uintptr_t rb_info;
|
||||
#define RB_FLAG_POSITION 0x2
|
||||
#define RB_FLAG_RED 0x1
|
||||
#define RB_FLAG_MASK (RB_FLAG_POSITION|RB_FLAG_RED)
|
||||
#define RB_FATHER(rb) \
|
||||
((struct rb_node *)((rb)->rb_info & ~RB_FLAG_MASK))
|
||||
#define RB_SET_FATHER(rb, father) \
|
||||
((void)((rb)->rb_info = (uintptr_t)(father)|((rb)->rb_info & RB_FLAG_MASK)))
|
||||
|
||||
#define RB_SENTINEL_P(rb) ((rb) == NULL)
|
||||
#define RB_LEFT_SENTINEL_P(rb) RB_SENTINEL_P((rb)->rb_left)
|
||||
#define RB_RIGHT_SENTINEL_P(rb) RB_SENTINEL_P((rb)->rb_right)
|
||||
#define RB_FATHER_SENTINEL_P(rb) RB_SENTINEL_P(RB_FATHER((rb)))
|
||||
#define RB_CHILDLESS_P(rb) \
|
||||
(RB_SENTINEL_P(rb) || (RB_LEFT_SENTINEL_P(rb) && RB_RIGHT_SENTINEL_P(rb)))
|
||||
#define RB_TWOCHILDREN_P(rb) \
|
||||
(!RB_SENTINEL_P(rb) && !RB_LEFT_SENTINEL_P(rb) && !RB_RIGHT_SENTINEL_P(rb))
|
||||
|
||||
#define RB_POSITION(rb) \
|
||||
(((rb)->rb_info & RB_FLAG_POSITION) ? RB_DIR_RIGHT : RB_DIR_LEFT)
|
||||
#define RB_RIGHT_P(rb) (RB_POSITION(rb) == RB_DIR_RIGHT)
|
||||
#define RB_LEFT_P(rb) (RB_POSITION(rb) == RB_DIR_LEFT)
|
||||
#define RB_RED_P(rb) (!RB_SENTINEL_P(rb) && ((rb)->rb_info & RB_FLAG_RED) != 0)
|
||||
#define RB_BLACK_P(rb) (RB_SENTINEL_P(rb) || ((rb)->rb_info & RB_FLAG_RED) == 0)
|
||||
#define RB_MARK_RED(rb) ((void)((rb)->rb_info |= RB_FLAG_RED))
|
||||
#define RB_MARK_BLACK(rb) ((void)((rb)->rb_info &= ~RB_FLAG_RED))
|
||||
#define RB_INVERT_COLOR(rb) ((void)((rb)->rb_info ^= RB_FLAG_RED))
|
||||
#define RB_ROOT_P(rbt, rb) ((rbt)->rbt_root == (rb))
|
||||
#define RB_SET_POSITION(rb, position) \
|
||||
((void)((position) ? ((rb)->rb_info |= RB_FLAG_POSITION) : \
|
||||
((rb)->rb_info &= ~RB_FLAG_POSITION)))
|
||||
#define RB_ZERO_PROPERTIES(rb) ((void)((rb)->rb_info &= ~RB_FLAG_MASK))
|
||||
#define RB_COPY_PROPERTIES(dst, src) \
|
||||
((void)((dst)->rb_info ^= ((dst)->rb_info ^ (src)->rb_info) & RB_FLAG_MASK))
|
||||
#define RB_SWAP_PROPERTIES(a, b) do { \
|
||||
uintptr_t xorinfo = ((a)->rb_info ^ (b)->rb_info) & RB_FLAG_MASK; \
|
||||
(a)->rb_info ^= xorinfo; \
|
||||
(b)->rb_info ^= xorinfo; \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
#ifdef RBDEBUG
|
||||
TAILQ_ENTRY(rb_node) rb_link;
|
||||
#endif
|
||||
} rb_node_t;
|
||||
|
||||
#define RB_TREE_MIN(T) rb_tree_iterate((T), NULL, RB_DIR_LEFT)
|
||||
#define RB_TREE_MAX(T) rb_tree_iterate((T), NULL, RB_DIR_RIGHT)
|
||||
#define RB_TREE_FOREACH(N, T) \
|
||||
for ((N) = RB_TREE_MIN(T); (N); \
|
||||
(N) = rb_tree_iterate((T), (N), RB_DIR_RIGHT))
|
||||
#define RB_TREE_FOREACH_REVERSE(N, T) \
|
||||
for ((N) = RB_TREE_MAX(T); (N); \
|
||||
(N) = rb_tree_iterate((T), (N), RB_DIR_LEFT))
|
||||
|
||||
#ifdef RBDEBUG
|
||||
TAILQ_HEAD(rb_node_qh, rb_node);
|
||||
|
||||
#define RB_TAILQ_REMOVE(a, b, c) TAILQ_REMOVE(a, b, c)
|
||||
#define RB_TAILQ_INIT(a) TAILQ_INIT(a)
|
||||
#define RB_TAILQ_INSERT_HEAD(a, b, c) TAILQ_INSERT_HEAD(a, b, c)
|
||||
#define RB_TAILQ_INSERT_BEFORE(a, b, c) TAILQ_INSERT_BEFORE(a, b, c)
|
||||
#define RB_TAILQ_INSERT_AFTER(a, b, c, d) TAILQ_INSERT_AFTER(a, b, c, d)
|
||||
#else
|
||||
#define RB_TAILQ_REMOVE(a, b, c) do { } while (/*CONSTCOND*/0)
|
||||
#define RB_TAILQ_INIT(a) do { } while (/*CONSTCOND*/0)
|
||||
#define RB_TAILQ_INSERT_HEAD(a, b, c) do { } while (/*CONSTCOND*/0)
|
||||
#define RB_TAILQ_INSERT_BEFORE(a, b, c) do { } while (/*CONSTCOND*/0)
|
||||
#define RB_TAILQ_INSERT_AFTER(a, b, c, d) do { } while (/*CONSTCOND*/0)
|
||||
#endif /* RBDEBUG */
|
||||
|
||||
/*
|
||||
* rbto_compare_nodes_fn:
|
||||
* return a positive value if the first node > the second node.
|
||||
* return a negative value if the first node < the second node.
|
||||
* return 0 if they are considered same.
|
||||
*
|
||||
* rbto_compare_key_fn:
|
||||
* return a positive value if the node > the key.
|
||||
* return a negative value if the node < the key.
|
||||
* return 0 if they are considered same.
|
||||
*/
|
||||
|
||||
typedef signed int (*const rbto_compare_nodes_fn)(void *,
|
||||
const void *, const void *);
|
||||
typedef signed int (*const rbto_compare_key_fn)(void *,
|
||||
const void *, const void *);
|
||||
|
||||
typedef struct {
|
||||
rbto_compare_nodes_fn rbto_compare_nodes;
|
||||
rbto_compare_key_fn rbto_compare_key;
|
||||
size_t rbto_node_offset;
|
||||
void *rbto_context;
|
||||
} rb_tree_ops_t;
|
||||
|
||||
typedef struct rb_tree {
|
||||
struct rb_node *rbt_root;
|
||||
const rb_tree_ops_t *rbt_ops;
|
||||
struct rb_node *rbt_minmax[2];
|
||||
#ifdef RBDEBUG
|
||||
struct rb_node_qh rbt_nodes;
|
||||
#endif
|
||||
#ifdef RBSTATS
|
||||
unsigned int rbt_count;
|
||||
unsigned int rbt_insertions;
|
||||
unsigned int rbt_removals;
|
||||
unsigned int rbt_insertion_rebalance_calls;
|
||||
unsigned int rbt_insertion_rebalance_passes;
|
||||
unsigned int rbt_removal_rebalance_calls;
|
||||
unsigned int rbt_removal_rebalance_passes;
|
||||
#endif
|
||||
} rb_tree_t;
|
||||
|
||||
#ifdef RBSTATS
|
||||
#define RBSTAT_INC(v) ((void)((v)++))
|
||||
#define RBSTAT_DEC(v) ((void)((v)--))
|
||||
#else
|
||||
#define RBSTAT_INC(v) do { } while (/*CONSTCOND*/0)
|
||||
#define RBSTAT_DEC(v) do { } while (/*CONSTCOND*/0)
|
||||
#endif
|
||||
|
||||
void rb_tree_init(rb_tree_t *, const rb_tree_ops_t *);
|
||||
void * rb_tree_insert_node(rb_tree_t *, void *);
|
||||
void * rb_tree_find_node(rb_tree_t *, const void *);
|
||||
void * rb_tree_find_node_geq(rb_tree_t *, const void *);
|
||||
void * rb_tree_find_node_leq(rb_tree_t *, const void *);
|
||||
void rb_tree_remove_node(rb_tree_t *, void *);
|
||||
void * rb_tree_iterate(rb_tree_t *, void *, const unsigned int);
|
||||
#ifdef RBDEBUG
|
||||
void rb_tree_check(const rb_tree_t *, bool);
|
||||
#endif
|
||||
#ifdef RBSTATS
|
||||
void rb_tree_depths(const rb_tree_t *, size_t *);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#endif /* _SYS_RBTREE_H_*/
|
||||
962
lib/external/portableproplib/prop_array.c
vendored
Normal file
962
lib/external/portableproplib/prop_array.c
vendored
Normal file
@@ -0,0 +1,962 @@
|
||||
/* $NetBSD: prop_array.c,v 1.21 2012/07/27 09:10:59 pooka Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2006, 2007 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Jason R. Thorpe.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "prop_object_impl.h"
|
||||
#include <prop/prop_array.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
struct _prop_array {
|
||||
struct _prop_object pa_obj;
|
||||
_PROP_RWLOCK_DECL(pa_rwlock)
|
||||
prop_object_t * pa_array;
|
||||
unsigned int pa_capacity;
|
||||
unsigned int pa_count;
|
||||
int pa_flags;
|
||||
|
||||
uint32_t pa_version;
|
||||
};
|
||||
|
||||
#define PA_F_IMMUTABLE 0x01 /* array is immutable */
|
||||
|
||||
_PROP_POOL_INIT(_prop_array_pool, sizeof(struct _prop_array), "proparay")
|
||||
|
||||
static _prop_object_free_rv_t
|
||||
_prop_array_free(prop_stack_t, prop_object_t *);
|
||||
static void _prop_array_emergency_free(prop_object_t);
|
||||
static bool _prop_array_externalize(
|
||||
struct _prop_object_externalize_context *,
|
||||
void *);
|
||||
static _prop_object_equals_rv_t
|
||||
_prop_array_equals(prop_object_t, prop_object_t,
|
||||
void **, void **,
|
||||
prop_object_t *, prop_object_t *);
|
||||
static void _prop_array_equals_finish(prop_object_t, prop_object_t);
|
||||
static prop_object_iterator_t
|
||||
_prop_array_iterator_locked(prop_array_t);
|
||||
static prop_object_t
|
||||
_prop_array_iterator_next_object_locked(void *);
|
||||
static void _prop_array_iterator_reset_locked(void *);
|
||||
|
||||
static const struct _prop_object_type _prop_object_type_array = {
|
||||
.pot_type = PROP_TYPE_ARRAY,
|
||||
.pot_free = _prop_array_free,
|
||||
.pot_emergency_free = _prop_array_emergency_free,
|
||||
.pot_extern = _prop_array_externalize,
|
||||
.pot_equals = _prop_array_equals,
|
||||
.pot_equals_finish = _prop_array_equals_finish,
|
||||
};
|
||||
|
||||
#define prop_object_is_array(x) \
|
||||
((x) != NULL && (x)->pa_obj.po_type == &_prop_object_type_array)
|
||||
|
||||
#define prop_array_is_immutable(x) (((x)->pa_flags & PA_F_IMMUTABLE) != 0)
|
||||
|
||||
struct _prop_array_iterator {
|
||||
struct _prop_object_iterator pai_base;
|
||||
unsigned int pai_index;
|
||||
};
|
||||
|
||||
#define EXPAND_STEP 16
|
||||
|
||||
static _prop_object_free_rv_t
|
||||
_prop_array_free(prop_stack_t stack, prop_object_t *obj)
|
||||
{
|
||||
prop_array_t pa = *obj;
|
||||
prop_object_t po;
|
||||
|
||||
_PROP_ASSERT(pa->pa_count <= pa->pa_capacity);
|
||||
_PROP_ASSERT((pa->pa_capacity == 0 && pa->pa_array == NULL) ||
|
||||
(pa->pa_capacity != 0 && pa->pa_array != NULL));
|
||||
|
||||
/* The easy case is an empty array, just free and return. */
|
||||
if (pa->pa_count == 0) {
|
||||
if (pa->pa_array != NULL)
|
||||
_PROP_FREE(pa->pa_array, M_PROP_ARRAY);
|
||||
|
||||
_PROP_RWLOCK_DESTROY(pa->pa_rwlock);
|
||||
|
||||
_PROP_POOL_PUT(_prop_array_pool, pa);
|
||||
|
||||
return (_PROP_OBJECT_FREE_DONE);
|
||||
}
|
||||
|
||||
po = pa->pa_array[pa->pa_count - 1];
|
||||
_PROP_ASSERT(po != NULL);
|
||||
|
||||
if (stack == NULL) {
|
||||
/*
|
||||
* If we are in emergency release mode,
|
||||
* just let caller recurse down.
|
||||
*/
|
||||
*obj = po;
|
||||
return (_PROP_OBJECT_FREE_FAILED);
|
||||
}
|
||||
|
||||
/* Otherwise, try to push the current object on the stack. */
|
||||
if (!_prop_stack_push(stack, pa, NULL, NULL, NULL)) {
|
||||
/* Push failed, entering emergency release mode. */
|
||||
return (_PROP_OBJECT_FREE_FAILED);
|
||||
}
|
||||
/* Object pushed on stack, caller will release it. */
|
||||
--pa->pa_count;
|
||||
*obj = po;
|
||||
return (_PROP_OBJECT_FREE_RECURSE);
|
||||
}
|
||||
|
||||
static void
|
||||
_prop_array_emergency_free(prop_object_t obj)
|
||||
{
|
||||
prop_array_t pa = obj;
|
||||
|
||||
_PROP_ASSERT(pa->pa_count != 0);
|
||||
--pa->pa_count;
|
||||
}
|
||||
|
||||
static bool
|
||||
_prop_array_externalize(struct _prop_object_externalize_context *ctx,
|
||||
void *v)
|
||||
{
|
||||
prop_array_t pa = v;
|
||||
struct _prop_object *po;
|
||||
prop_object_iterator_t pi;
|
||||
unsigned int i;
|
||||
bool rv = false;
|
||||
|
||||
_PROP_RWLOCK_RDLOCK(pa->pa_rwlock);
|
||||
|
||||
if (pa->pa_count == 0) {
|
||||
_PROP_RWLOCK_UNLOCK(pa->pa_rwlock);
|
||||
return (_prop_object_externalize_empty_tag(ctx, "array"));
|
||||
}
|
||||
|
||||
/* XXXJRT Hint "count" for the internalize step? */
|
||||
if (_prop_object_externalize_start_tag(ctx, "array") == false ||
|
||||
_prop_object_externalize_append_char(ctx, '\n') == false)
|
||||
goto out;
|
||||
|
||||
pi = _prop_array_iterator_locked(pa);
|
||||
if (pi == NULL)
|
||||
goto out;
|
||||
|
||||
ctx->poec_depth++;
|
||||
_PROP_ASSERT(ctx->poec_depth != 0);
|
||||
|
||||
while ((po = _prop_array_iterator_next_object_locked(pi)) != NULL) {
|
||||
if ((*po->po_type->pot_extern)(ctx, po) == false) {
|
||||
prop_object_iterator_release(pi);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
prop_object_iterator_release(pi);
|
||||
|
||||
ctx->poec_depth--;
|
||||
for (i = 0; i < ctx->poec_depth; i++) {
|
||||
if (_prop_object_externalize_append_char(ctx, '\t') == false)
|
||||
goto out;
|
||||
}
|
||||
if (_prop_object_externalize_end_tag(ctx, "array") == false)
|
||||
goto out;
|
||||
|
||||
rv = true;
|
||||
|
||||
out:
|
||||
_PROP_RWLOCK_UNLOCK(pa->pa_rwlock);
|
||||
return (rv);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static _prop_object_equals_rv_t
|
||||
_prop_array_equals(prop_object_t v1, prop_object_t v2,
|
||||
void **stored_pointer1, void **stored_pointer2,
|
||||
prop_object_t *next_obj1, prop_object_t *next_obj2)
|
||||
{
|
||||
prop_array_t array1 = v1;
|
||||
prop_array_t array2 = v2;
|
||||
uintptr_t idx;
|
||||
_prop_object_equals_rv_t rv = _PROP_OBJECT_EQUALS_FALSE;
|
||||
|
||||
if (array1 == array2)
|
||||
return (_PROP_OBJECT_EQUALS_TRUE);
|
||||
|
||||
_PROP_ASSERT(*stored_pointer1 == *stored_pointer2);
|
||||
idx = (uintptr_t)*stored_pointer1;
|
||||
|
||||
/* For the first iteration, lock the objects. */
|
||||
if (idx == 0) {
|
||||
if ((uintptr_t)array1 < (uintptr_t)array2) {
|
||||
_PROP_RWLOCK_RDLOCK(array1->pa_rwlock);
|
||||
_PROP_RWLOCK_RDLOCK(array2->pa_rwlock);
|
||||
} else {
|
||||
_PROP_RWLOCK_RDLOCK(array2->pa_rwlock);
|
||||
_PROP_RWLOCK_RDLOCK(array1->pa_rwlock);
|
||||
}
|
||||
}
|
||||
|
||||
if (array1->pa_count != array2->pa_count)
|
||||
goto out;
|
||||
if (idx == array1->pa_count) {
|
||||
rv = _PROP_OBJECT_EQUALS_TRUE;
|
||||
goto out;
|
||||
}
|
||||
_PROP_ASSERT(idx < array1->pa_count);
|
||||
|
||||
*stored_pointer1 = (void *)(idx + 1);
|
||||
*stored_pointer2 = (void *)(idx + 1);
|
||||
|
||||
*next_obj1 = array1->pa_array[idx];
|
||||
*next_obj2 = array2->pa_array[idx];
|
||||
|
||||
return (_PROP_OBJECT_EQUALS_RECURSE);
|
||||
|
||||
out:
|
||||
_PROP_RWLOCK_UNLOCK(array1->pa_rwlock);
|
||||
_PROP_RWLOCK_UNLOCK(array2->pa_rwlock);
|
||||
return (rv);
|
||||
}
|
||||
|
||||
static void
|
||||
_prop_array_equals_finish(prop_object_t v1, prop_object_t v2)
|
||||
{
|
||||
_PROP_RWLOCK_UNLOCK(((prop_array_t)v1)->pa_rwlock);
|
||||
_PROP_RWLOCK_UNLOCK(((prop_array_t)v2)->pa_rwlock);
|
||||
}
|
||||
|
||||
static prop_array_t
|
||||
_prop_array_alloc(unsigned int capacity)
|
||||
{
|
||||
prop_array_t pa;
|
||||
prop_object_t *array;
|
||||
|
||||
if (capacity != 0) {
|
||||
array = _PROP_CALLOC(capacity * sizeof(prop_object_t),
|
||||
M_PROP_ARRAY);
|
||||
if (array == NULL)
|
||||
return (NULL);
|
||||
} else
|
||||
array = NULL;
|
||||
|
||||
pa = _PROP_POOL_GET(_prop_array_pool);
|
||||
if (pa != NULL) {
|
||||
_prop_object_init(&pa->pa_obj, &_prop_object_type_array);
|
||||
pa->pa_obj.po_type = &_prop_object_type_array;
|
||||
|
||||
_PROP_RWLOCK_INIT(pa->pa_rwlock);
|
||||
pa->pa_array = array;
|
||||
pa->pa_capacity = capacity;
|
||||
pa->pa_count = 0;
|
||||
pa->pa_flags = 0;
|
||||
|
||||
pa->pa_version = 0;
|
||||
} else if (array != NULL)
|
||||
_PROP_FREE(array, M_PROP_ARRAY);
|
||||
|
||||
return (pa);
|
||||
}
|
||||
|
||||
static bool
|
||||
_prop_array_expand(prop_array_t pa, unsigned int capacity)
|
||||
{
|
||||
prop_object_t *array, *oarray;
|
||||
|
||||
/*
|
||||
* Array must be WRITE-LOCKED.
|
||||
*/
|
||||
|
||||
oarray = pa->pa_array;
|
||||
|
||||
array = _PROP_CALLOC(capacity * sizeof(*array), M_PROP_ARRAY);
|
||||
if (array == NULL)
|
||||
return (false);
|
||||
if (oarray != NULL)
|
||||
memcpy(array, oarray, pa->pa_capacity * sizeof(*array));
|
||||
pa->pa_array = array;
|
||||
pa->pa_capacity = capacity;
|
||||
|
||||
if (oarray != NULL)
|
||||
_PROP_FREE(oarray, M_PROP_ARRAY);
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
static prop_object_t
|
||||
_prop_array_iterator_next_object_locked(void *v)
|
||||
{
|
||||
struct _prop_array_iterator *pai = v;
|
||||
prop_array_t pa = pai->pai_base.pi_obj;
|
||||
prop_object_t po = NULL;
|
||||
|
||||
_PROP_ASSERT(prop_object_is_array(pa));
|
||||
|
||||
if (pa->pa_version != pai->pai_base.pi_version)
|
||||
goto out; /* array changed during iteration */
|
||||
|
||||
_PROP_ASSERT(pai->pai_index <= pa->pa_count);
|
||||
|
||||
if (pai->pai_index == pa->pa_count)
|
||||
goto out; /* we've iterated all objects */
|
||||
|
||||
po = pa->pa_array[pai->pai_index];
|
||||
pai->pai_index++;
|
||||
|
||||
out:
|
||||
return (po);
|
||||
}
|
||||
|
||||
static prop_object_t
|
||||
_prop_array_iterator_next_object(void *v)
|
||||
{
|
||||
struct _prop_array_iterator *pai = v;
|
||||
prop_array_t pa _PROP_ARG_UNUSED = pai->pai_base.pi_obj;
|
||||
prop_object_t po;
|
||||
|
||||
_PROP_ASSERT(prop_object_is_array(pa));
|
||||
|
||||
_PROP_RWLOCK_RDLOCK(pa->pa_rwlock);
|
||||
po = _prop_array_iterator_next_object_locked(pai);
|
||||
_PROP_RWLOCK_UNLOCK(pa->pa_rwlock);
|
||||
return (po);
|
||||
}
|
||||
|
||||
static void
|
||||
_prop_array_iterator_reset_locked(void *v)
|
||||
{
|
||||
struct _prop_array_iterator *pai = v;
|
||||
prop_array_t pa = pai->pai_base.pi_obj;
|
||||
|
||||
_PROP_ASSERT(prop_object_is_array(pa));
|
||||
|
||||
pai->pai_index = 0;
|
||||
pai->pai_base.pi_version = pa->pa_version;
|
||||
}
|
||||
|
||||
static void
|
||||
_prop_array_iterator_reset(void *v)
|
||||
{
|
||||
struct _prop_array_iterator *pai = v;
|
||||
prop_array_t pa _PROP_ARG_UNUSED = pai->pai_base.pi_obj;
|
||||
|
||||
_PROP_ASSERT(prop_object_is_array(pa));
|
||||
|
||||
_PROP_RWLOCK_RDLOCK(pa->pa_rwlock);
|
||||
_prop_array_iterator_reset_locked(pai);
|
||||
_PROP_RWLOCK_UNLOCK(pa->pa_rwlock);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_array_create --
|
||||
* Create an empty array.
|
||||
*/
|
||||
prop_array_t
|
||||
prop_array_create(void)
|
||||
{
|
||||
|
||||
return (_prop_array_alloc(0));
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_array_create_with_capacity --
|
||||
* Create an array with the capacity to store N objects.
|
||||
*/
|
||||
prop_array_t
|
||||
prop_array_create_with_capacity(unsigned int capacity)
|
||||
{
|
||||
|
||||
return (_prop_array_alloc(capacity));
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_array_copy --
|
||||
* Copy an array. The new array has an initial capacity equal to
|
||||
* the number of objects stored in the original array. The new
|
||||
* array contains references to the original array's objects, not
|
||||
* copies of those objects (i.e. a shallow copy).
|
||||
*/
|
||||
prop_array_t
|
||||
prop_array_copy(prop_array_t opa)
|
||||
{
|
||||
prop_array_t pa;
|
||||
prop_object_t po;
|
||||
unsigned int idx;
|
||||
|
||||
if (! prop_object_is_array(opa))
|
||||
return (NULL);
|
||||
|
||||
_PROP_RWLOCK_RDLOCK(opa->pa_rwlock);
|
||||
|
||||
pa = _prop_array_alloc(opa->pa_count);
|
||||
if (pa != NULL) {
|
||||
for (idx = 0; idx < opa->pa_count; idx++) {
|
||||
po = opa->pa_array[idx];
|
||||
prop_object_retain(po);
|
||||
pa->pa_array[idx] = po;
|
||||
}
|
||||
pa->pa_count = opa->pa_count;
|
||||
pa->pa_flags = opa->pa_flags;
|
||||
}
|
||||
_PROP_RWLOCK_UNLOCK(opa->pa_rwlock);
|
||||
return (pa);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_array_copy_mutable --
|
||||
* Like prop_array_copy(), but the resulting array is mutable.
|
||||
*/
|
||||
prop_array_t
|
||||
prop_array_copy_mutable(prop_array_t opa)
|
||||
{
|
||||
prop_array_t pa;
|
||||
|
||||
pa = prop_array_copy(opa);
|
||||
if (pa != NULL)
|
||||
pa->pa_flags &= ~PA_F_IMMUTABLE;
|
||||
|
||||
return (pa);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_array_capacity --
|
||||
* Return the capacity of the array.
|
||||
*/
|
||||
unsigned int
|
||||
prop_array_capacity(prop_array_t pa)
|
||||
{
|
||||
unsigned int rv;
|
||||
|
||||
if (! prop_object_is_array(pa))
|
||||
return (0);
|
||||
|
||||
_PROP_RWLOCK_RDLOCK(pa->pa_rwlock);
|
||||
rv = pa->pa_capacity;
|
||||
_PROP_RWLOCK_UNLOCK(pa->pa_rwlock);
|
||||
|
||||
return (rv);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_array_count --
|
||||
* Return the number of objects stored in the array.
|
||||
*/
|
||||
unsigned int
|
||||
prop_array_count(prop_array_t pa)
|
||||
{
|
||||
unsigned int rv;
|
||||
|
||||
if (! prop_object_is_array(pa))
|
||||
return (0);
|
||||
|
||||
_PROP_RWLOCK_RDLOCK(pa->pa_rwlock);
|
||||
rv = pa->pa_count;
|
||||
_PROP_RWLOCK_UNLOCK(pa->pa_rwlock);
|
||||
|
||||
return (rv);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_array_ensure_capacity --
|
||||
* Ensure that the array has the capacity to store the specified
|
||||
* total number of objects (inluding the objects already stored
|
||||
* in the array).
|
||||
*/
|
||||
bool
|
||||
prop_array_ensure_capacity(prop_array_t pa, unsigned int capacity)
|
||||
{
|
||||
bool rv;
|
||||
|
||||
if (! prop_object_is_array(pa))
|
||||
return (false);
|
||||
|
||||
_PROP_RWLOCK_WRLOCK(pa->pa_rwlock);
|
||||
if (capacity > pa->pa_capacity)
|
||||
rv = _prop_array_expand(pa, capacity);
|
||||
else
|
||||
rv = true;
|
||||
_PROP_RWLOCK_UNLOCK(pa->pa_rwlock);
|
||||
|
||||
return (rv);
|
||||
}
|
||||
|
||||
static prop_object_iterator_t
|
||||
_prop_array_iterator_locked(prop_array_t pa)
|
||||
{
|
||||
struct _prop_array_iterator *pai;
|
||||
|
||||
if (! prop_object_is_array(pa))
|
||||
return (NULL);
|
||||
|
||||
pai = _PROP_CALLOC(sizeof(*pai), M_TEMP);
|
||||
if (pai == NULL)
|
||||
return (NULL);
|
||||
pai->pai_base.pi_next_object = _prop_array_iterator_next_object;
|
||||
pai->pai_base.pi_reset = _prop_array_iterator_reset;
|
||||
prop_object_retain(pa);
|
||||
pai->pai_base.pi_obj = pa;
|
||||
_prop_array_iterator_reset_locked(pai);
|
||||
|
||||
return (&pai->pai_base);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_array_iterator --
|
||||
* Return an iterator for the array. The array is retained by
|
||||
* the iterator.
|
||||
*/
|
||||
prop_object_iterator_t
|
||||
prop_array_iterator(prop_array_t pa)
|
||||
{
|
||||
prop_object_iterator_t pi;
|
||||
|
||||
_PROP_RWLOCK_RDLOCK(pa->pa_rwlock);
|
||||
pi = _prop_array_iterator_locked(pa);
|
||||
_PROP_RWLOCK_UNLOCK(pa->pa_rwlock);
|
||||
return (pi);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_array_make_immutable --
|
||||
* Make the array immutable.
|
||||
*/
|
||||
void
|
||||
prop_array_make_immutable(prop_array_t pa)
|
||||
{
|
||||
|
||||
_PROP_RWLOCK_WRLOCK(pa->pa_rwlock);
|
||||
if (prop_array_is_immutable(pa) == false)
|
||||
pa->pa_flags |= PA_F_IMMUTABLE;
|
||||
_PROP_RWLOCK_UNLOCK(pa->pa_rwlock);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_array_mutable --
|
||||
* Returns true if the array is mutable.
|
||||
*/
|
||||
bool
|
||||
prop_array_mutable(prop_array_t pa)
|
||||
{
|
||||
bool rv;
|
||||
|
||||
_PROP_RWLOCK_RDLOCK(pa->pa_rwlock);
|
||||
rv = prop_array_is_immutable(pa) == false;
|
||||
_PROP_RWLOCK_UNLOCK(pa->pa_rwlock);
|
||||
|
||||
return (rv);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_array_get --
|
||||
* Return the object stored at the specified array index.
|
||||
*/
|
||||
prop_object_t
|
||||
prop_array_get(prop_array_t pa, unsigned int idx)
|
||||
{
|
||||
prop_object_t po = NULL;
|
||||
|
||||
if (! prop_object_is_array(pa))
|
||||
return (NULL);
|
||||
|
||||
_PROP_RWLOCK_RDLOCK(pa->pa_rwlock);
|
||||
if (idx >= pa->pa_count)
|
||||
goto out;
|
||||
po = pa->pa_array[idx];
|
||||
_PROP_ASSERT(po != NULL);
|
||||
out:
|
||||
_PROP_RWLOCK_UNLOCK(pa->pa_rwlock);
|
||||
return (po);
|
||||
}
|
||||
|
||||
static bool
|
||||
_prop_array_add(prop_array_t pa, prop_object_t po)
|
||||
{
|
||||
|
||||
/*
|
||||
* Array must be WRITE-LOCKED.
|
||||
*/
|
||||
|
||||
_PROP_ASSERT(pa->pa_count <= pa->pa_capacity);
|
||||
|
||||
if (prop_array_is_immutable(pa) ||
|
||||
(pa->pa_count == pa->pa_capacity &&
|
||||
_prop_array_expand(pa, pa->pa_capacity + EXPAND_STEP) == false))
|
||||
return (false);
|
||||
|
||||
prop_object_retain(po);
|
||||
pa->pa_array[pa->pa_count++] = po;
|
||||
pa->pa_version++;
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
static bool
|
||||
_prop_array_add_first(prop_array_t pa, prop_object_t po)
|
||||
{
|
||||
unsigned int cnt;
|
||||
/*
|
||||
* Array must be WRITE-LOCKED.
|
||||
*/
|
||||
|
||||
_PROP_ASSERT(pa->pa_count <= pa->pa_capacity);
|
||||
|
||||
if (prop_array_is_immutable(pa) ||
|
||||
(pa->pa_count == pa->pa_capacity &&
|
||||
_prop_array_expand(pa, pa->pa_capacity + EXPAND_STEP) == false))
|
||||
return false;
|
||||
|
||||
prop_object_retain(po);
|
||||
if (pa->pa_count) {
|
||||
cnt = pa->pa_count+1;
|
||||
/* move all stored elements to the right */
|
||||
while (--cnt) {
|
||||
prop_object_t opo = pa->pa_array[cnt-1];
|
||||
_PROP_ASSERT(opo != NULL);
|
||||
prop_object_retain(opo);
|
||||
pa->pa_array[cnt] = opo;
|
||||
prop_object_release(opo);
|
||||
}
|
||||
/* passed in object is now the first element */
|
||||
pa->pa_array[0] = po;
|
||||
pa->pa_version++;
|
||||
pa->pa_count++;
|
||||
} else {
|
||||
pa->pa_array[pa->pa_count++] = po;
|
||||
pa->pa_version++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_array_set --
|
||||
* Store a reference to an object at the specified array index.
|
||||
* This method is not allowed to create holes in the array; the
|
||||
* caller must either be setting the object just beyond the existing
|
||||
* count or replacing an already existing object reference.
|
||||
*/
|
||||
bool
|
||||
prop_array_set(prop_array_t pa, unsigned int idx, prop_object_t po)
|
||||
{
|
||||
prop_object_t opo;
|
||||
bool rv = false;
|
||||
|
||||
if (! prop_object_is_array(pa))
|
||||
return (false);
|
||||
|
||||
_PROP_RWLOCK_WRLOCK(pa->pa_rwlock);
|
||||
|
||||
if (prop_array_is_immutable(pa))
|
||||
goto out;
|
||||
|
||||
if (idx == pa->pa_count) {
|
||||
rv = _prop_array_add(pa, po);
|
||||
goto out;
|
||||
}
|
||||
|
||||
_PROP_ASSERT(idx < pa->pa_count);
|
||||
|
||||
opo = pa->pa_array[idx];
|
||||
_PROP_ASSERT(opo != NULL);
|
||||
|
||||
prop_object_retain(po);
|
||||
pa->pa_array[idx] = po;
|
||||
pa->pa_version++;
|
||||
|
||||
prop_object_release(opo);
|
||||
|
||||
rv = true;
|
||||
|
||||
out:
|
||||
_PROP_RWLOCK_UNLOCK(pa->pa_rwlock);
|
||||
return (rv);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_array_add --
|
||||
* Add a reference to an object to the specified array, appending
|
||||
* to the end and growing the array's capacity, if necessary.
|
||||
*/
|
||||
bool
|
||||
prop_array_add(prop_array_t pa, prop_object_t po)
|
||||
{
|
||||
bool rv;
|
||||
|
||||
if (! prop_object_is_array(pa))
|
||||
return (false);
|
||||
|
||||
_PROP_RWLOCK_WRLOCK(pa->pa_rwlock);
|
||||
rv = _prop_array_add(pa, po);
|
||||
_PROP_RWLOCK_UNLOCK(pa->pa_rwlock);
|
||||
|
||||
return (rv);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_array_add_first --
|
||||
* Add a reference to an object to the specified array, inserting it
|
||||
* as first element, moving all objects to the right and growing the
|
||||
* array's capacity, if necessary.
|
||||
*/
|
||||
bool
|
||||
prop_array_add_first(prop_array_t pa, prop_object_t po)
|
||||
{
|
||||
bool rv;
|
||||
|
||||
if (! prop_object_is_array(pa))
|
||||
return (false);
|
||||
|
||||
_PROP_RWLOCK_WRLOCK(pa->pa_rwlock);
|
||||
rv = _prop_array_add_first(pa, po);
|
||||
_PROP_RWLOCK_UNLOCK(pa->pa_rwlock);
|
||||
|
||||
return (rv);
|
||||
}
|
||||
/*
|
||||
* prop_array_remove --
|
||||
* Remove the reference to an object from an array at the specified
|
||||
* index. The array will be compacted following the removal.
|
||||
*/
|
||||
void
|
||||
prop_array_remove(prop_array_t pa, unsigned int idx)
|
||||
{
|
||||
prop_object_t po;
|
||||
|
||||
if (! prop_object_is_array(pa))
|
||||
return;
|
||||
|
||||
_PROP_RWLOCK_WRLOCK(pa->pa_rwlock);
|
||||
|
||||
_PROP_ASSERT(idx < pa->pa_count);
|
||||
|
||||
/* XXX Should this be a _PROP_ASSERT()? */
|
||||
if (prop_array_is_immutable(pa)) {
|
||||
_PROP_RWLOCK_UNLOCK(pa->pa_rwlock);
|
||||
return;
|
||||
}
|
||||
|
||||
po = pa->pa_array[idx];
|
||||
_PROP_ASSERT(po != NULL);
|
||||
|
||||
for (++idx; idx < pa->pa_count; idx++)
|
||||
pa->pa_array[idx - 1] = pa->pa_array[idx];
|
||||
pa->pa_count--;
|
||||
pa->pa_version++;
|
||||
|
||||
_PROP_RWLOCK_UNLOCK(pa->pa_rwlock);
|
||||
|
||||
prop_object_release(po);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_array_equals --
|
||||
* Return true if the two arrays are equivalent. Note we do a
|
||||
* by-value comparison of the objects in the array.
|
||||
*/
|
||||
bool
|
||||
prop_array_equals(prop_array_t array1, prop_array_t array2)
|
||||
{
|
||||
if (!prop_object_is_array(array1) || !prop_object_is_array(array2))
|
||||
return (false);
|
||||
|
||||
return (prop_object_equals(array1, array2));
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_array_externalize --
|
||||
* Externalize an array, return a NUL-terminated buffer
|
||||
* containing the XML-style representation. The buffer is allocated
|
||||
* with the M_TEMP memory type.
|
||||
*/
|
||||
char *
|
||||
prop_array_externalize(prop_array_t pa)
|
||||
{
|
||||
struct _prop_object_externalize_context *ctx;
|
||||
char *cp;
|
||||
|
||||
ctx = _prop_object_externalize_context_alloc();
|
||||
if (ctx == NULL)
|
||||
return (NULL);
|
||||
|
||||
if (_prop_object_externalize_header(ctx) == false ||
|
||||
(*pa->pa_obj.po_type->pot_extern)(ctx, pa) == false ||
|
||||
_prop_object_externalize_footer(ctx) == false) {
|
||||
/* We are responsible for releasing the buffer. */
|
||||
_PROP_FREE(ctx->poec_buf, M_TEMP);
|
||||
_prop_object_externalize_context_free(ctx);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
cp = ctx->poec_buf;
|
||||
_prop_object_externalize_context_free(ctx);
|
||||
|
||||
return (cp);
|
||||
}
|
||||
|
||||
/*
|
||||
* _prop_array_internalize --
|
||||
* Parse an <array>...</array> and return the object created from the
|
||||
* external representation.
|
||||
*/
|
||||
static bool _prop_array_internalize_body(prop_stack_t, prop_object_t *,
|
||||
struct _prop_object_internalize_context *);
|
||||
|
||||
bool
|
||||
_prop_array_internalize(prop_stack_t stack, prop_object_t *obj,
|
||||
struct _prop_object_internalize_context *ctx)
|
||||
{
|
||||
/* We don't currently understand any attributes. */
|
||||
if (ctx->poic_tagattr != NULL)
|
||||
return (true);
|
||||
|
||||
*obj = prop_array_create();
|
||||
/*
|
||||
* We are done if the create failed or no child elements exist.
|
||||
*/
|
||||
if (*obj == NULL || ctx->poic_is_empty_element)
|
||||
return (true);
|
||||
|
||||
/*
|
||||
* Opening tag is found, now continue to the first element.
|
||||
*/
|
||||
return (_prop_array_internalize_body(stack, obj, ctx));
|
||||
}
|
||||
|
||||
static bool
|
||||
_prop_array_internalize_continue(prop_stack_t stack,
|
||||
prop_object_t *obj,
|
||||
struct _prop_object_internalize_context *ctx,
|
||||
void *data, prop_object_t child)
|
||||
{
|
||||
prop_array_t array;
|
||||
|
||||
_PROP_ASSERT(data == NULL);
|
||||
|
||||
if (child == NULL)
|
||||
goto bad; /* Element could not be parsed. */
|
||||
|
||||
array = *obj;
|
||||
|
||||
if (prop_array_add(array, child) == false) {
|
||||
prop_object_release(child);
|
||||
goto bad;
|
||||
}
|
||||
prop_object_release(child);
|
||||
|
||||
/*
|
||||
* Current element is processed and added, look for next.
|
||||
*/
|
||||
return (_prop_array_internalize_body(stack, obj, ctx));
|
||||
|
||||
bad:
|
||||
prop_object_release(*obj);
|
||||
*obj = NULL;
|
||||
return (true);
|
||||
}
|
||||
|
||||
static bool
|
||||
_prop_array_internalize_body(prop_stack_t stack, prop_object_t *obj,
|
||||
struct _prop_object_internalize_context *ctx)
|
||||
{
|
||||
prop_array_t array = *obj;
|
||||
|
||||
_PROP_ASSERT(array != NULL);
|
||||
|
||||
/* Fetch the next tag. */
|
||||
if (_prop_object_internalize_find_tag(ctx, NULL,
|
||||
_PROP_TAG_TYPE_EITHER) == false)
|
||||
goto bad;
|
||||
|
||||
/* Check to see if this is the end of the array. */
|
||||
if (_PROP_TAG_MATCH(ctx, "array") &&
|
||||
ctx->poic_tag_type == _PROP_TAG_TYPE_END) {
|
||||
/* It is, so don't iterate any further. */
|
||||
return (true);
|
||||
}
|
||||
|
||||
if (_prop_stack_push(stack, array,
|
||||
_prop_array_internalize_continue, NULL, NULL))
|
||||
return (false);
|
||||
|
||||
bad:
|
||||
prop_object_release(array);
|
||||
*obj = NULL;
|
||||
return (true);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_array_internalize --
|
||||
* Create an array by parsing the XML-style representation.
|
||||
*/
|
||||
prop_array_t
|
||||
prop_array_internalize(const char *xml)
|
||||
{
|
||||
return _prop_generic_internalize(xml, "array");
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_array_externalize_to_file --
|
||||
* Externalize an array to the specified file.
|
||||
*/
|
||||
bool
|
||||
prop_array_externalize_to_file(prop_array_t array, const char *fname)
|
||||
{
|
||||
char *xml;
|
||||
bool rv;
|
||||
int save_errno = 0; /* XXXGCC -Wuninitialized [mips, ...] */
|
||||
|
||||
xml = prop_array_externalize(array);
|
||||
if (xml == NULL)
|
||||
return (false);
|
||||
rv = _prop_object_externalize_write_file(fname, xml, strlen(xml), false);
|
||||
if (rv == false)
|
||||
save_errno = errno;
|
||||
_PROP_FREE(xml, M_TEMP);
|
||||
if (rv == false)
|
||||
errno = save_errno;
|
||||
|
||||
return (rv);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_array_internalize_from_file --
|
||||
* Internalize an array from a file.
|
||||
*/
|
||||
prop_array_t
|
||||
prop_array_internalize_from_file(const char *fname)
|
||||
{
|
||||
struct _prop_object_internalize_mapped_file *mf;
|
||||
prop_array_t array;
|
||||
|
||||
mf = _prop_object_internalize_map_file(fname);
|
||||
if (mf == NULL)
|
||||
return (NULL);
|
||||
array = prop_array_internalize(mf->poimf_xml);
|
||||
_prop_object_internalize_unmap_file(mf);
|
||||
|
||||
return (array);
|
||||
}
|
||||
266
lib/external/portableproplib/prop_array_util.c
vendored
Normal file
266
lib/external/portableproplib/prop_array_util.c
vendored
Normal file
@@ -0,0 +1,266 @@
|
||||
/* $NetBSD: prop_array_util.c,v 1.4 2012/07/27 09:10:59 pooka Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2006 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Jason R. Thorpe.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Utility routines to make it more convenient to work with values
|
||||
* stored in array.
|
||||
*
|
||||
* Note: There is no special magic going on here. We use the standard
|
||||
* proplib(3) APIs to do all of this work. Any application could do
|
||||
* exactly what we're doing here.
|
||||
*/
|
||||
|
||||
#include "prop_object_impl.h" /* hide kernel vs. not-kernel vs. standalone */
|
||||
#include <prop/proplib.h>
|
||||
|
||||
bool
|
||||
prop_array_get_bool(prop_array_t array,
|
||||
unsigned int indx,
|
||||
bool *valp)
|
||||
{
|
||||
prop_bool_t b;
|
||||
|
||||
b = prop_array_get(array, indx);
|
||||
if (prop_object_type(b) != PROP_TYPE_BOOL)
|
||||
return (false);
|
||||
|
||||
*valp = prop_bool_true(b);
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
bool
|
||||
prop_array_set_bool(prop_array_t array,
|
||||
unsigned int indx,
|
||||
bool val)
|
||||
{
|
||||
prop_bool_t b;
|
||||
int rv;
|
||||
|
||||
b = prop_bool_create(val);
|
||||
if (b == NULL)
|
||||
return (false);
|
||||
rv = prop_array_set(array, indx, b);
|
||||
prop_object_release(b);
|
||||
|
||||
return (rv);
|
||||
}
|
||||
|
||||
#define TEMPLATE(size) \
|
||||
bool \
|
||||
prop_array_get_int ## size (prop_array_t array, \
|
||||
unsigned int indx, \
|
||||
int ## size ## _t *valp) \
|
||||
{ \
|
||||
prop_number_t num; \
|
||||
\
|
||||
num = prop_array_get(array, indx); \
|
||||
if (prop_object_type(num) != PROP_TYPE_NUMBER) \
|
||||
return (false); \
|
||||
\
|
||||
if (prop_number_unsigned(num) && \
|
||||
prop_number_unsigned_integer_value(num) > \
|
||||
/*CONSTCOND*/((size) == 8 ? INT8_MAX : \
|
||||
(size) == 16 ? INT16_MAX : \
|
||||
(size) == 32 ? INT32_MAX : INT64_MAX)) { \
|
||||
return (false); \
|
||||
} \
|
||||
\
|
||||
if (prop_number_size(num) > (size)) \
|
||||
return (false); \
|
||||
\
|
||||
*valp = (int ## size ## _t) prop_number_integer_value(num); \
|
||||
\
|
||||
return (true); \
|
||||
} \
|
||||
\
|
||||
bool \
|
||||
prop_array_get_uint ## size (prop_array_t array, \
|
||||
unsigned int indx, \
|
||||
uint ## size ## _t *valp) \
|
||||
{ \
|
||||
prop_number_t num; \
|
||||
\
|
||||
num = prop_array_get(array, indx); \
|
||||
if (prop_object_type(num) != PROP_TYPE_NUMBER) \
|
||||
return (false); \
|
||||
\
|
||||
if (prop_number_unsigned(num) == false && \
|
||||
prop_number_integer_value(num) < 0) { \
|
||||
return (false); \
|
||||
} \
|
||||
\
|
||||
if (prop_number_size(num) > (size)) \
|
||||
return (false); \
|
||||
\
|
||||
*valp = (uint ## size ## _t) \
|
||||
prop_number_unsigned_integer_value(num); \
|
||||
\
|
||||
return (true); \
|
||||
} \
|
||||
\
|
||||
bool \
|
||||
prop_array_set_int ## size (prop_array_t array, \
|
||||
unsigned int indx, \
|
||||
int ## size ## _t val) \
|
||||
{ \
|
||||
prop_number_t num; \
|
||||
int rv; \
|
||||
\
|
||||
num = prop_number_create_integer((int64_t) val); \
|
||||
if (num == NULL) \
|
||||
return (false); \
|
||||
rv = prop_array_set(array, indx, num); \
|
||||
prop_object_release(num); \
|
||||
\
|
||||
return (rv); \
|
||||
} \
|
||||
\
|
||||
bool \
|
||||
prop_array_set_uint ## size (prop_array_t array, \
|
||||
unsigned int indx, \
|
||||
uint ## size ## _t val) \
|
||||
{ \
|
||||
prop_number_t num; \
|
||||
int rv; \
|
||||
\
|
||||
num = prop_number_create_unsigned_integer((uint64_t) val); \
|
||||
if (num == NULL) \
|
||||
return (false); \
|
||||
rv = prop_array_set(array, indx, num); \
|
||||
prop_object_release(num); \
|
||||
\
|
||||
return (rv); \
|
||||
} \
|
||||
\
|
||||
bool \
|
||||
prop_array_add_int ## size (prop_array_t array, \
|
||||
int ## size ## _t val) \
|
||||
{ \
|
||||
prop_number_t num; \
|
||||
int rv; \
|
||||
\
|
||||
num = prop_number_create_integer((int64_t) val); \
|
||||
if (num == NULL) \
|
||||
return (false); \
|
||||
rv = prop_array_add(array, num); \
|
||||
prop_object_release(num); \
|
||||
\
|
||||
return (rv); \
|
||||
} \
|
||||
\
|
||||
bool \
|
||||
prop_array_add_uint ## size (prop_array_t array, \
|
||||
uint ## size ## _t val) \
|
||||
{ \
|
||||
prop_number_t num; \
|
||||
int rv; \
|
||||
\
|
||||
num = prop_number_create_integer((int64_t) val); \
|
||||
if (num == NULL) \
|
||||
return (false); \
|
||||
rv = prop_array_add(array, num); \
|
||||
prop_object_release(num); \
|
||||
\
|
||||
return (rv); \
|
||||
}
|
||||
|
||||
TEMPLATE(8)
|
||||
TEMPLATE(16)
|
||||
TEMPLATE(32)
|
||||
TEMPLATE(64)
|
||||
|
||||
#undef TEMPLATE
|
||||
|
||||
#define TEMPLATE(variant, qualifier) \
|
||||
bool \
|
||||
prop_array_get_cstring ## variant (prop_array_t array, \
|
||||
unsigned int indx, \
|
||||
qualifier char **cpp) \
|
||||
{ \
|
||||
prop_string_t str; \
|
||||
\
|
||||
str = prop_array_get(array, indx); \
|
||||
if (prop_object_type(str) != PROP_TYPE_STRING) \
|
||||
return (false); \
|
||||
\
|
||||
*cpp = prop_string_cstring ## variant (str); \
|
||||
\
|
||||
return (*cpp == NULL ? false : true); \
|
||||
} \
|
||||
\
|
||||
bool \
|
||||
prop_array_add_cstring ## variant (prop_array_t array, \
|
||||
const char *cp) \
|
||||
{ \
|
||||
prop_string_t str; \
|
||||
bool rv; \
|
||||
\
|
||||
str = prop_string_create_cstring ## variant (cp); \
|
||||
if (str == NULL) \
|
||||
return false; \
|
||||
rv = prop_array_add(array, str); \
|
||||
prop_object_release(str); \
|
||||
return rv; \
|
||||
} \
|
||||
\
|
||||
bool \
|
||||
prop_array_set_cstring ## variant (prop_array_t array, \
|
||||
unsigned int indx, \
|
||||
const char *cp) \
|
||||
{ \
|
||||
prop_string_t str; \
|
||||
int rv; \
|
||||
\
|
||||
str = prop_string_create_cstring ## variant (cp); \
|
||||
if (str == NULL) \
|
||||
return (false); \
|
||||
rv = prop_array_set(array, indx, str); \
|
||||
prop_object_release(str); \
|
||||
\
|
||||
return (rv); \
|
||||
}
|
||||
|
||||
TEMPLATE(,)
|
||||
TEMPLATE(_nocopy,const)
|
||||
|
||||
#undef TEMPLATE
|
||||
|
||||
bool
|
||||
prop_array_add_and_rel(prop_array_t array, prop_object_t po)
|
||||
{
|
||||
bool ret;
|
||||
if (po == NULL)
|
||||
return false;
|
||||
ret = prop_array_add(array, po);
|
||||
prop_object_release(po);
|
||||
return ret;
|
||||
}
|
||||
222
lib/external/portableproplib/prop_bool.c
vendored
Normal file
222
lib/external/portableproplib/prop_bool.c
vendored
Normal file
@@ -0,0 +1,222 @@
|
||||
/* $NetBSD: prop_bool.c,v 1.17 2009/01/03 18:31:33 pooka Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2006 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Jason R. Thorpe.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <prop/prop_bool.h>
|
||||
#include "prop_object_impl.h"
|
||||
|
||||
struct _prop_bool {
|
||||
struct _prop_object pb_obj;
|
||||
bool pb_value;
|
||||
};
|
||||
|
||||
static struct _prop_bool _prop_bool_true;
|
||||
static struct _prop_bool _prop_bool_false;
|
||||
|
||||
static _prop_object_free_rv_t
|
||||
_prop_bool_free(prop_stack_t, prop_object_t *);
|
||||
static bool _prop_bool_externalize(
|
||||
struct _prop_object_externalize_context *,
|
||||
void *);
|
||||
static _prop_object_equals_rv_t
|
||||
_prop_bool_equals(prop_object_t, prop_object_t,
|
||||
void **, void **,
|
||||
prop_object_t *, prop_object_t *);
|
||||
|
||||
static const struct _prop_object_type _prop_object_type_bool = {
|
||||
.pot_type = PROP_TYPE_BOOL,
|
||||
.pot_free = _prop_bool_free,
|
||||
.pot_extern = _prop_bool_externalize,
|
||||
.pot_equals = _prop_bool_equals,
|
||||
};
|
||||
|
||||
#define prop_object_is_bool(x) \
|
||||
((x) != NULL && (x)->pb_obj.po_type == &_prop_object_type_bool)
|
||||
|
||||
/* ARGSUSED */
|
||||
static _prop_object_free_rv_t
|
||||
_prop_bool_free(prop_stack_t stack, prop_object_t *obj)
|
||||
{
|
||||
/*
|
||||
* This should never happen as we "leak" our initial reference
|
||||
* count.
|
||||
*/
|
||||
|
||||
/* XXX forced assertion failure? */
|
||||
return (_PROP_OBJECT_FREE_DONE);
|
||||
}
|
||||
|
||||
static bool
|
||||
_prop_bool_externalize(struct _prop_object_externalize_context *ctx,
|
||||
void *v)
|
||||
{
|
||||
prop_bool_t pb = v;
|
||||
|
||||
return (_prop_object_externalize_empty_tag(ctx,
|
||||
pb->pb_value ? "true" : "false"));
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static _prop_object_equals_rv_t
|
||||
_prop_bool_equals(prop_object_t v1, prop_object_t v2,
|
||||
void **stored_pointer1, void **stored_pointer2,
|
||||
prop_object_t *next_obj1, prop_object_t *next_obj2)
|
||||
{
|
||||
prop_bool_t b1 = v1;
|
||||
prop_bool_t b2 = v2;
|
||||
|
||||
if (! (prop_object_is_bool(b1) &&
|
||||
prop_object_is_bool(b2)))
|
||||
return (_PROP_OBJECT_EQUALS_FALSE);
|
||||
|
||||
/*
|
||||
* Since we only ever allocate one true and one false,
|
||||
* save ourselves a couple of memory operations.
|
||||
*/
|
||||
if (b1 == b2)
|
||||
return (_PROP_OBJECT_EQUALS_TRUE);
|
||||
else
|
||||
return (_PROP_OBJECT_EQUALS_FALSE);
|
||||
}
|
||||
|
||||
_PROP_ONCE_DECL(_prop_bool_init_once)
|
||||
|
||||
static int
|
||||
_prop_bool_init(void)
|
||||
{
|
||||
|
||||
_prop_object_init(&_prop_bool_true.pb_obj,
|
||||
&_prop_object_type_bool);
|
||||
_prop_bool_true.pb_value = true;
|
||||
|
||||
_prop_object_init(&_prop_bool_false.pb_obj,
|
||||
&_prop_object_type_bool);
|
||||
_prop_bool_false.pb_value = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static prop_bool_t
|
||||
_prop_bool_alloc(bool val)
|
||||
{
|
||||
prop_bool_t pb;
|
||||
|
||||
_PROP_ONCE_RUN(_prop_bool_init_once, _prop_bool_init);
|
||||
pb = val ? &_prop_bool_true : &_prop_bool_false;
|
||||
prop_object_retain(pb);
|
||||
|
||||
return (pb);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_bool_create --
|
||||
* Create a prop_bool_t and initialize it with the
|
||||
* provided boolean value.
|
||||
*/
|
||||
prop_bool_t
|
||||
prop_bool_create(bool val)
|
||||
{
|
||||
|
||||
return (_prop_bool_alloc(val));
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_bool_copy --
|
||||
* Copy a prop_bool_t.
|
||||
*/
|
||||
prop_bool_t
|
||||
prop_bool_copy(prop_bool_t opb)
|
||||
{
|
||||
|
||||
if (! prop_object_is_bool(opb))
|
||||
return (NULL);
|
||||
|
||||
/*
|
||||
* Because we only ever allocate one true and one false, this
|
||||
* can be reduced to a simple retain operation.
|
||||
*/
|
||||
prop_object_retain(opb);
|
||||
return (opb);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_bool_true --
|
||||
* Get the value of a prop_bool_t.
|
||||
*/
|
||||
bool
|
||||
prop_bool_true(prop_bool_t pb)
|
||||
{
|
||||
|
||||
if (! prop_object_is_bool(pb))
|
||||
return (false);
|
||||
|
||||
return (pb->pb_value);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_bool_equals --
|
||||
* Return true if the boolean values are equivalent.
|
||||
*/
|
||||
bool
|
||||
prop_bool_equals(prop_bool_t b1, prop_bool_t b2)
|
||||
{
|
||||
if (!prop_object_is_bool(b1) || !prop_object_is_bool(b2))
|
||||
return (false);
|
||||
|
||||
return (prop_object_equals(b1, b2));
|
||||
}
|
||||
|
||||
/*
|
||||
* _prop_bool_internalize --
|
||||
* Parse a <true/> or <false/> and return the object created from
|
||||
* the external representation.
|
||||
*/
|
||||
|
||||
/* ARGSUSED */
|
||||
bool
|
||||
_prop_bool_internalize(prop_stack_t stack, prop_object_t *obj,
|
||||
struct _prop_object_internalize_context *ctx)
|
||||
{
|
||||
bool val;
|
||||
|
||||
/* No attributes, and it must be an empty element. */
|
||||
if (ctx->poic_tagattr != NULL ||
|
||||
ctx->poic_is_empty_element == false)
|
||||
return (true);
|
||||
|
||||
if (_PROP_TAG_MATCH(ctx, "true"))
|
||||
val = true;
|
||||
else {
|
||||
_PROP_ASSERT(_PROP_TAG_MATCH(ctx, "false"));
|
||||
val = false;
|
||||
}
|
||||
*obj = prop_bool_create(val);
|
||||
return (true);
|
||||
}
|
||||
614
lib/external/portableproplib/prop_data.c
vendored
Normal file
614
lib/external/portableproplib/prop_data.c
vendored
Normal file
@@ -0,0 +1,614 @@
|
||||
/* $NetBSD: prop_data.c,v 1.13 2008/08/03 04:00:12 thorpej Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2006 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Jason R. Thorpe.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <prop/prop_data.h>
|
||||
#include "prop_object_impl.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
struct _prop_data {
|
||||
struct _prop_object pd_obj;
|
||||
union {
|
||||
void * pdu_mutable;
|
||||
const void * pdu_immutable;
|
||||
} pd_un;
|
||||
#define pd_mutable pd_un.pdu_mutable
|
||||
#define pd_immutable pd_un.pdu_immutable
|
||||
size_t pd_size;
|
||||
int pd_flags;
|
||||
};
|
||||
|
||||
#define PD_F_NOCOPY 0x01
|
||||
|
||||
_PROP_POOL_INIT(_prop_data_pool, sizeof(struct _prop_data), "propdata")
|
||||
|
||||
static _prop_object_free_rv_t
|
||||
_prop_data_free(prop_stack_t, prop_object_t *);
|
||||
static bool _prop_data_externalize(
|
||||
struct _prop_object_externalize_context *,
|
||||
void *);
|
||||
static _prop_object_equals_rv_t
|
||||
_prop_data_equals(prop_object_t, prop_object_t,
|
||||
void **, void **,
|
||||
prop_object_t *, prop_object_t *);
|
||||
|
||||
static const struct _prop_object_type _prop_object_type_data = {
|
||||
.pot_type = PROP_TYPE_DATA,
|
||||
.pot_free = _prop_data_free,
|
||||
.pot_extern = _prop_data_externalize,
|
||||
.pot_equals = _prop_data_equals,
|
||||
};
|
||||
|
||||
#define prop_object_is_data(x) \
|
||||
((x) != NULL && (x)->pd_obj.po_type == &_prop_object_type_data)
|
||||
|
||||
/* ARGSUSED */
|
||||
static _prop_object_free_rv_t
|
||||
_prop_data_free(prop_stack_t stack, prop_object_t *obj)
|
||||
{
|
||||
prop_data_t pd = *obj;
|
||||
|
||||
if ((pd->pd_flags & PD_F_NOCOPY) == 0 && pd->pd_mutable != NULL)
|
||||
_PROP_FREE(pd->pd_mutable, M_PROP_DATA);
|
||||
_PROP_POOL_PUT(_prop_data_pool, pd);
|
||||
|
||||
return (_PROP_OBJECT_FREE_DONE);
|
||||
}
|
||||
|
||||
static const char _prop_data_base64[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
static const char _prop_data_pad64 = '=';
|
||||
|
||||
static bool
|
||||
_prop_data_externalize(struct _prop_object_externalize_context *ctx, void *v)
|
||||
{
|
||||
prop_data_t pd = v;
|
||||
size_t i, srclen;
|
||||
const uint8_t *src;
|
||||
uint8_t output[4];
|
||||
uint8_t input[3];
|
||||
|
||||
if (pd->pd_size == 0)
|
||||
return (_prop_object_externalize_empty_tag(ctx, "data"));
|
||||
|
||||
if (_prop_object_externalize_start_tag(ctx, "data") == false)
|
||||
return (false);
|
||||
|
||||
for (src = pd->pd_immutable, srclen = pd->pd_size;
|
||||
srclen > 2; srclen -= 3) {
|
||||
input[0] = *src++;
|
||||
input[1] = *src++;
|
||||
input[2] = *src++;
|
||||
|
||||
output[0] = (uint32_t)input[0] >> 2;
|
||||
output[1] = ((uint32_t)(input[0] & 0x03) << 4) +
|
||||
((uint32_t)input[1] >> 4);
|
||||
output[2] = ((uint32_t)(input[1] & 0x0f) << 2) +
|
||||
((uint32_t)input[2] >> 6);
|
||||
output[3] = input[2] & 0x3f;
|
||||
_PROP_ASSERT(output[0] < 64);
|
||||
_PROP_ASSERT(output[1] < 64);
|
||||
_PROP_ASSERT(output[2] < 64);
|
||||
_PROP_ASSERT(output[3] < 64);
|
||||
|
||||
if (_prop_object_externalize_append_char(ctx,
|
||||
_prop_data_base64[output[0]]) == false ||
|
||||
_prop_object_externalize_append_char(ctx,
|
||||
_prop_data_base64[output[1]]) == false ||
|
||||
_prop_object_externalize_append_char(ctx,
|
||||
_prop_data_base64[output[2]]) == false ||
|
||||
_prop_object_externalize_append_char(ctx,
|
||||
_prop_data_base64[output[3]]) == false)
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (srclen != 0) {
|
||||
input[0] = input[1] = input[2] = '\0';
|
||||
for (i = 0; i < srclen; i++)
|
||||
input[i] = *src++;
|
||||
|
||||
output[0] = (uint32_t)input[0] >> 2;
|
||||
output[1] = ((uint32_t)(input[0] & 0x03) << 4) +
|
||||
((uint32_t)input[1] >> 4);
|
||||
output[2] = ((uint32_t)(input[1] & 0x0f) << 2) +
|
||||
((uint32_t)input[2] >> 6);
|
||||
_PROP_ASSERT(output[0] < 64);
|
||||
_PROP_ASSERT(output[1] < 64);
|
||||
_PROP_ASSERT(output[2] < 64);
|
||||
|
||||
if (_prop_object_externalize_append_char(ctx,
|
||||
_prop_data_base64[output[0]]) == false ||
|
||||
_prop_object_externalize_append_char(ctx,
|
||||
_prop_data_base64[output[1]]) == false ||
|
||||
_prop_object_externalize_append_char(ctx,
|
||||
srclen == 1 ? _prop_data_pad64
|
||||
: _prop_data_base64[output[2]]) == false ||
|
||||
_prop_object_externalize_append_char(ctx,
|
||||
_prop_data_pad64) == false)
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (_prop_object_externalize_end_tag(ctx, "data") == false)
|
||||
return (false);
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static _prop_object_equals_rv_t
|
||||
_prop_data_equals(prop_object_t v1, prop_object_t v2,
|
||||
void **stored_pointer1, void **stored_pointer2,
|
||||
prop_object_t *next_obj1, prop_object_t *next_obj2)
|
||||
{
|
||||
prop_data_t pd1 = v1;
|
||||
prop_data_t pd2 = v2;
|
||||
|
||||
if (pd1 == pd2)
|
||||
return (_PROP_OBJECT_EQUALS_TRUE);
|
||||
if (pd1->pd_size != pd2->pd_size)
|
||||
return (_PROP_OBJECT_EQUALS_FALSE);
|
||||
if (pd1->pd_size == 0) {
|
||||
_PROP_ASSERT(pd1->pd_immutable == NULL);
|
||||
_PROP_ASSERT(pd2->pd_immutable == NULL);
|
||||
return (_PROP_OBJECT_EQUALS_TRUE);
|
||||
}
|
||||
if (memcmp(pd1->pd_immutable, pd2->pd_immutable, pd1->pd_size) == 0)
|
||||
return _PROP_OBJECT_EQUALS_TRUE;
|
||||
else
|
||||
return _PROP_OBJECT_EQUALS_FALSE;
|
||||
}
|
||||
|
||||
static prop_data_t
|
||||
_prop_data_alloc(void)
|
||||
{
|
||||
prop_data_t pd;
|
||||
|
||||
pd = _PROP_POOL_GET(_prop_data_pool);
|
||||
if (pd != NULL) {
|
||||
_prop_object_init(&pd->pd_obj, &_prop_object_type_data);
|
||||
|
||||
pd->pd_mutable = NULL;
|
||||
pd->pd_size = 0;
|
||||
pd->pd_flags = 0;
|
||||
}
|
||||
|
||||
return (pd);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_data_create_data --
|
||||
* Create a data container that contains a copy of the data.
|
||||
*/
|
||||
prop_data_t
|
||||
prop_data_create_data(const void *v, size_t size)
|
||||
{
|
||||
prop_data_t pd;
|
||||
void *nv;
|
||||
|
||||
pd = _prop_data_alloc();
|
||||
if (pd != NULL && size != 0) {
|
||||
nv = _PROP_MALLOC(size, M_PROP_DATA);
|
||||
if (nv == NULL) {
|
||||
prop_object_release(pd);
|
||||
return (NULL);
|
||||
}
|
||||
memcpy(nv, v, size);
|
||||
pd->pd_mutable = nv;
|
||||
pd->pd_size = size;
|
||||
}
|
||||
return (pd);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_data_create_data_nocopy --
|
||||
* Create an immutable data container that contains a refrence to the
|
||||
* provided external data.
|
||||
*/
|
||||
prop_data_t
|
||||
prop_data_create_data_nocopy(const void *v, size_t size)
|
||||
{
|
||||
prop_data_t pd;
|
||||
|
||||
pd = _prop_data_alloc();
|
||||
if (pd != NULL) {
|
||||
pd->pd_immutable = v;
|
||||
pd->pd_size = size;
|
||||
pd->pd_flags |= PD_F_NOCOPY;
|
||||
}
|
||||
return (pd);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_data_copy --
|
||||
* Copy a data container. If the original data is external, then
|
||||
* the copy is also references the same external data.
|
||||
*/
|
||||
prop_data_t
|
||||
prop_data_copy(prop_data_t opd)
|
||||
{
|
||||
prop_data_t pd;
|
||||
|
||||
if (! prop_object_is_data(opd))
|
||||
return (NULL);
|
||||
|
||||
pd = _prop_data_alloc();
|
||||
if (pd != NULL) {
|
||||
pd->pd_size = opd->pd_size;
|
||||
pd->pd_flags = opd->pd_flags;
|
||||
if (opd->pd_flags & PD_F_NOCOPY)
|
||||
pd->pd_immutable = opd->pd_immutable;
|
||||
else if (opd->pd_size != 0) {
|
||||
void *nv = _PROP_MALLOC(pd->pd_size, M_PROP_DATA);
|
||||
if (nv == NULL) {
|
||||
prop_object_release(pd);
|
||||
return (NULL);
|
||||
}
|
||||
memcpy(nv, opd->pd_immutable, opd->pd_size);
|
||||
pd->pd_mutable = nv;
|
||||
}
|
||||
}
|
||||
return (pd);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_data_size --
|
||||
* Return the size of the data.
|
||||
*/
|
||||
size_t
|
||||
prop_data_size(prop_data_t pd)
|
||||
{
|
||||
|
||||
if (! prop_object_is_data(pd))
|
||||
return (0);
|
||||
|
||||
return (pd->pd_size);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_data_data --
|
||||
* Return a copy of the contents of the data container.
|
||||
* The data is allocated with the M_TEMP malloc type.
|
||||
* If the data container is empty, NULL is returned.
|
||||
*/
|
||||
void *
|
||||
prop_data_data(prop_data_t pd)
|
||||
{
|
||||
void *v;
|
||||
|
||||
if (! prop_object_is_data(pd))
|
||||
return (NULL);
|
||||
|
||||
if (pd->pd_size == 0) {
|
||||
_PROP_ASSERT(pd->pd_immutable == NULL);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
_PROP_ASSERT(pd->pd_immutable != NULL);
|
||||
|
||||
v = _PROP_MALLOC(pd->pd_size, M_TEMP);
|
||||
if (v != NULL)
|
||||
memcpy(v, pd->pd_immutable, pd->pd_size);
|
||||
|
||||
return (v);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_data_data_nocopy --
|
||||
* Return an immutable reference to the contents of the data
|
||||
* container.
|
||||
*/
|
||||
const void *
|
||||
prop_data_data_nocopy(prop_data_t pd)
|
||||
{
|
||||
|
||||
if (! prop_object_is_data(pd))
|
||||
return (NULL);
|
||||
|
||||
_PROP_ASSERT((pd->pd_size == 0 && pd->pd_immutable == NULL) ||
|
||||
(pd->pd_size != 0 && pd->pd_immutable != NULL));
|
||||
|
||||
return (pd->pd_immutable);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_data_equals --
|
||||
* Return true if two strings are equivalent.
|
||||
*/
|
||||
bool
|
||||
prop_data_equals(prop_data_t pd1, prop_data_t pd2)
|
||||
{
|
||||
if (!prop_object_is_data(pd1) || !prop_object_is_data(pd2))
|
||||
return (false);
|
||||
|
||||
return (prop_object_equals(pd1, pd2));
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_data_equals_data --
|
||||
* Return true if the contained data is equivalent to the specified
|
||||
* external data.
|
||||
*/
|
||||
bool
|
||||
prop_data_equals_data(prop_data_t pd, const void *v, size_t size)
|
||||
{
|
||||
|
||||
if (! prop_object_is_data(pd))
|
||||
return (false);
|
||||
|
||||
if (pd->pd_size != size)
|
||||
return (false);
|
||||
return (memcmp(pd->pd_immutable, v, size) == 0);
|
||||
}
|
||||
|
||||
static bool
|
||||
_prop_data_internalize_decode(struct _prop_object_internalize_context *ctx,
|
||||
uint8_t *target, size_t targsize, size_t *sizep,
|
||||
const char **cpp)
|
||||
{
|
||||
const char *src;
|
||||
size_t tarindex;
|
||||
int state, ch;
|
||||
const char *pos;
|
||||
|
||||
state = 0;
|
||||
tarindex = 0;
|
||||
src = ctx->poic_cp;
|
||||
|
||||
for (;;) {
|
||||
ch = (unsigned char) *src++;
|
||||
if (_PROP_EOF(ch))
|
||||
return (false);
|
||||
if (_PROP_ISSPACE(ch))
|
||||
continue;
|
||||
if (ch == '<') {
|
||||
src--;
|
||||
break;
|
||||
}
|
||||
if (ch == _prop_data_pad64)
|
||||
break;
|
||||
|
||||
pos = strchr(_prop_data_base64, ch);
|
||||
if (pos == NULL)
|
||||
return (false);
|
||||
|
||||
switch (state) {
|
||||
case 0:
|
||||
if (target) {
|
||||
if (tarindex >= targsize)
|
||||
return (false);
|
||||
target[tarindex] =
|
||||
(uint8_t)((pos - _prop_data_base64) << 2);
|
||||
}
|
||||
state = 1;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
if (target) {
|
||||
if (tarindex + 1 >= targsize)
|
||||
return (false);
|
||||
target[tarindex] |=
|
||||
(uint32_t)(pos - _prop_data_base64) >> 4;
|
||||
target[tarindex + 1] =
|
||||
(uint8_t)(((pos - _prop_data_base64) & 0xf)
|
||||
<< 4);
|
||||
}
|
||||
tarindex++;
|
||||
state = 2;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if (target) {
|
||||
if (tarindex + 1 >= targsize)
|
||||
return (false);
|
||||
target[tarindex] |=
|
||||
(uint32_t)(pos - _prop_data_base64) >> 2;
|
||||
target[tarindex + 1] =
|
||||
(uint8_t)(((pos - _prop_data_base64)
|
||||
& 0x3) << 6);
|
||||
}
|
||||
tarindex++;
|
||||
state = 3;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
if (target) {
|
||||
if (tarindex >= targsize)
|
||||
return (false);
|
||||
target[tarindex] |= (uint8_t)
|
||||
(pos - _prop_data_base64);
|
||||
}
|
||||
tarindex++;
|
||||
state = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
_PROP_ASSERT(/*CONSTCOND*/0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We are done decoding the Base64 characters. Let's see if we
|
||||
* ended up on a byte boundary and/or with unrecognized trailing
|
||||
* characters.
|
||||
*/
|
||||
if (ch == _prop_data_pad64) {
|
||||
ch = (unsigned char) *src; /* src already advanced */
|
||||
if (_PROP_EOF(ch))
|
||||
return (false);
|
||||
switch (state) {
|
||||
case 0: /* Invalid = in first position */
|
||||
case 1: /* Invalid = in second position */
|
||||
return (false);
|
||||
|
||||
case 2: /* Valid, one byte of info */
|
||||
/* Skip whitespace */
|
||||
for (ch = (unsigned char) *src++;
|
||||
ch != '<'; ch = (unsigned char) *src++) {
|
||||
if (_PROP_EOF(ch))
|
||||
return (false);
|
||||
if (!_PROP_ISSPACE(ch))
|
||||
break;
|
||||
}
|
||||
/* Make sure there is another trailing = */
|
||||
if (ch != _prop_data_pad64)
|
||||
return (false);
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case 3: /* Valid, two bytes of info */
|
||||
/*
|
||||
* We know this char is a =. Is there anything but
|
||||
* whitespace after it?
|
||||
*/
|
||||
for (ch = (unsigned char) *src++;
|
||||
ch != '<'; ch = (unsigned char) *src++) {
|
||||
if (_PROP_EOF(ch))
|
||||
return (false);
|
||||
if (!_PROP_ISSPACE(ch))
|
||||
return (false);
|
||||
}
|
||||
/* back up to '<' */
|
||||
src--;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* We ended by seeing the end of the Base64 string. Make
|
||||
* sure there are no partial bytes lying around.
|
||||
*/
|
||||
if (state != 0)
|
||||
return (false);
|
||||
}
|
||||
|
||||
_PROP_ASSERT(*src == '<');
|
||||
if (sizep != NULL)
|
||||
*sizep = tarindex;
|
||||
if (cpp != NULL)
|
||||
*cpp = src;
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
/*
|
||||
* _prop_data_internalize --
|
||||
* Parse a <data>...</data> and return the object created from the
|
||||
* external representation.
|
||||
*/
|
||||
|
||||
/* strtoul is used for parsing, enforce. */
|
||||
typedef int PROP_DATA_ASSERT[/* CONSTCOND */sizeof(size_t) == sizeof(unsigned long) ? 1 : -1];
|
||||
|
||||
/* ARGSUSED */
|
||||
bool
|
||||
_prop_data_internalize(prop_stack_t stack, prop_object_t *obj,
|
||||
struct _prop_object_internalize_context *ctx)
|
||||
{
|
||||
prop_data_t data;
|
||||
uint8_t *buf;
|
||||
size_t len, alen;
|
||||
|
||||
/*
|
||||
* We don't accept empty elements.
|
||||
* This actually only checks for the node to be <data/>
|
||||
* (Which actually causes another error if found.)
|
||||
*/
|
||||
if (ctx->poic_is_empty_element)
|
||||
return (true);
|
||||
|
||||
/*
|
||||
* If we got a "size" attribute, get the size of the data blob
|
||||
* from that. Otherwise, we have to figure it out from the base64.
|
||||
*/
|
||||
if (ctx->poic_tagattr != NULL) {
|
||||
char *cp;
|
||||
|
||||
if (!_PROP_TAGATTR_MATCH(ctx, "size") ||
|
||||
ctx->poic_tagattrval_len == 0)
|
||||
return (true);
|
||||
|
||||
errno = 0;
|
||||
len = strtoul(ctx->poic_tagattrval, &cp, 0);
|
||||
if (len == ULONG_MAX && errno == ERANGE)
|
||||
return (true);
|
||||
if (cp != ctx->poic_tagattrval + ctx->poic_tagattrval_len)
|
||||
return (true);
|
||||
_PROP_ASSERT(*cp == '\"');
|
||||
} else if (_prop_data_internalize_decode(ctx, NULL, 0, &len,
|
||||
NULL) == false)
|
||||
return (true);
|
||||
|
||||
if (len >= SIZE_MAX)
|
||||
len = 1;
|
||||
/*
|
||||
* Always allocate one extra in case we don't land on an even byte
|
||||
* boundary during the decode.
|
||||
*/
|
||||
buf = _PROP_MALLOC(len + 1, M_PROP_DATA);
|
||||
if (buf == NULL)
|
||||
return (true);
|
||||
|
||||
if (_prop_data_internalize_decode(ctx, buf, len + 1, &alen,
|
||||
&ctx->poic_cp) == false) {
|
||||
_PROP_FREE(buf, M_PROP_DATA);
|
||||
return (true);
|
||||
}
|
||||
if (alen != len) {
|
||||
_PROP_FREE(buf, M_PROP_DATA);
|
||||
return (true);
|
||||
}
|
||||
|
||||
if (_prop_object_internalize_find_tag(ctx, "data",
|
||||
_PROP_TAG_TYPE_END) == false) {
|
||||
_PROP_FREE(buf, M_PROP_DATA);
|
||||
return (true);
|
||||
}
|
||||
|
||||
data = _prop_data_alloc();
|
||||
if (data == NULL) {
|
||||
_PROP_FREE(buf, M_PROP_DATA);
|
||||
return (true);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle alternate type of empty node.
|
||||
* XML document could contain open/close tags, yet still be empty.
|
||||
*/
|
||||
if (alen == 0) {
|
||||
_PROP_FREE(buf, M_PROP_DATA);
|
||||
data->pd_mutable = NULL;
|
||||
} else {
|
||||
data->pd_mutable = buf;
|
||||
}
|
||||
data->pd_size = len;
|
||||
|
||||
*obj = data;
|
||||
return (true);
|
||||
}
|
||||
1414
lib/external/portableproplib/prop_dictionary.c
vendored
Normal file
1414
lib/external/portableproplib/prop_dictionary.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
232
lib/external/portableproplib/prop_dictionary_util.c
vendored
Normal file
232
lib/external/portableproplib/prop_dictionary_util.c
vendored
Normal file
@@ -0,0 +1,232 @@
|
||||
/* $NetBSD: prop_dictionary_util.c,v 1.4 2011/03/24 17:05:39 bouyer Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2006 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Jason R. Thorpe.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Utility routines to make it more convenient to work with values
|
||||
* stored in dictionaries.
|
||||
*
|
||||
* Note: There is no special magic going on here. We use the standard
|
||||
* proplib(3) APIs to do all of this work. Any application could do
|
||||
* exactly what we're doing here.
|
||||
*/
|
||||
|
||||
#include <prop/proplib.h>
|
||||
#include "prop_object_impl.h" /* only to hide kernel vs. not-kernel */
|
||||
|
||||
bool
|
||||
prop_dictionary_get_dict(prop_dictionary_t dict, const char *key, prop_dictionary_t *dp)
|
||||
{
|
||||
prop_object_t o;
|
||||
o = prop_dictionary_get(dict, key);
|
||||
if (o == NULL || prop_object_type(o) != PROP_TYPE_DICTIONARY)
|
||||
return false;
|
||||
*dp = o;
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
bool
|
||||
prop_dictionary_get_bool(prop_dictionary_t dict,
|
||||
const char *key,
|
||||
bool *valp)
|
||||
{
|
||||
prop_bool_t b;
|
||||
|
||||
b = prop_dictionary_get(dict, key);
|
||||
if (prop_object_type(b) != PROP_TYPE_BOOL)
|
||||
return (false);
|
||||
|
||||
*valp = prop_bool_true(b);
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
bool
|
||||
prop_dictionary_set_bool(prop_dictionary_t dict,
|
||||
const char *key,
|
||||
bool val)
|
||||
{
|
||||
prop_bool_t b;
|
||||
int rv;
|
||||
|
||||
b = prop_bool_create(val);
|
||||
if (b == NULL)
|
||||
return (false);
|
||||
rv = prop_dictionary_set(dict, key, b);
|
||||
prop_object_release(b);
|
||||
|
||||
return (rv);
|
||||
}
|
||||
|
||||
#define TEMPLATE(size) \
|
||||
bool \
|
||||
prop_dictionary_get_int ## size (prop_dictionary_t dict, \
|
||||
const char *key, \
|
||||
int ## size ## _t *valp) \
|
||||
{ \
|
||||
prop_number_t num; \
|
||||
\
|
||||
num = prop_dictionary_get(dict, key); \
|
||||
if (prop_object_type(num) != PROP_TYPE_NUMBER) \
|
||||
return (false); \
|
||||
\
|
||||
if (prop_number_unsigned(num) && \
|
||||
prop_number_unsigned_integer_value(num) > \
|
||||
/*CONSTCOND*/((size) == 8 ? INT8_MAX : \
|
||||
(size) == 16 ? INT16_MAX : \
|
||||
(size) == 32 ? INT32_MAX : INT64_MAX)) { \
|
||||
return (false); \
|
||||
} \
|
||||
\
|
||||
if (prop_number_size(num) > (size)) \
|
||||
return (false); \
|
||||
\
|
||||
*valp = (int ## size ## _t) prop_number_integer_value(num); \
|
||||
\
|
||||
return (true); \
|
||||
} \
|
||||
\
|
||||
bool \
|
||||
prop_dictionary_get_uint ## size (prop_dictionary_t dict, \
|
||||
const char *key, \
|
||||
uint ## size ## _t *valp) \
|
||||
{ \
|
||||
prop_number_t num; \
|
||||
\
|
||||
num = prop_dictionary_get(dict, key); \
|
||||
if (prop_object_type(num) != PROP_TYPE_NUMBER) \
|
||||
return (false); \
|
||||
\
|
||||
if (prop_number_unsigned(num) == false && \
|
||||
prop_number_integer_value(num) < 0) { \
|
||||
return (false); \
|
||||
} \
|
||||
\
|
||||
if (prop_number_size(num) > (size)) \
|
||||
return (false); \
|
||||
\
|
||||
*valp = (uint ## size ## _t) \
|
||||
prop_number_unsigned_integer_value(num); \
|
||||
\
|
||||
return (true); \
|
||||
} \
|
||||
\
|
||||
bool \
|
||||
prop_dictionary_set_int ## size (prop_dictionary_t dict, \
|
||||
const char *key, \
|
||||
int ## size ## _t val) \
|
||||
{ \
|
||||
prop_number_t num; \
|
||||
int rv; \
|
||||
\
|
||||
num = prop_number_create_integer((int64_t) val); \
|
||||
if (num == NULL) \
|
||||
return (false); \
|
||||
rv = prop_dictionary_set(dict, key, num); \
|
||||
prop_object_release(num); \
|
||||
\
|
||||
return (rv); \
|
||||
} \
|
||||
\
|
||||
bool \
|
||||
prop_dictionary_set_uint ## size (prop_dictionary_t dict, \
|
||||
const char *key, \
|
||||
uint ## size ## _t val) \
|
||||
{ \
|
||||
prop_number_t num; \
|
||||
int rv; \
|
||||
\
|
||||
num = prop_number_create_unsigned_integer((uint64_t) val); \
|
||||
if (num == NULL) \
|
||||
return (false); \
|
||||
rv = prop_dictionary_set(dict, key, num); \
|
||||
prop_object_release(num); \
|
||||
\
|
||||
return (rv); \
|
||||
}
|
||||
|
||||
TEMPLATE(8)
|
||||
TEMPLATE(16)
|
||||
TEMPLATE(32)
|
||||
TEMPLATE(64)
|
||||
|
||||
#undef TEMPLATE
|
||||
|
||||
#define TEMPLATE(variant, qualifier) \
|
||||
bool \
|
||||
prop_dictionary_get_cstring ## variant (prop_dictionary_t dict, \
|
||||
const char *key, \
|
||||
qualifier char **cpp) \
|
||||
{ \
|
||||
prop_string_t str; \
|
||||
\
|
||||
str = prop_dictionary_get(dict, key); \
|
||||
if (prop_object_type(str) != PROP_TYPE_STRING) \
|
||||
return (false); \
|
||||
\
|
||||
*cpp = prop_string_cstring ## variant (str); \
|
||||
\
|
||||
return (*cpp == NULL ? false : true); \
|
||||
} \
|
||||
\
|
||||
bool \
|
||||
prop_dictionary_set_cstring ## variant (prop_dictionary_t dict, \
|
||||
const char *key, \
|
||||
const char *cp) \
|
||||
{ \
|
||||
prop_string_t str; \
|
||||
int rv; \
|
||||
\
|
||||
str = prop_string_create_cstring ## variant (cp); \
|
||||
if (str == NULL) \
|
||||
return (false); \
|
||||
rv = prop_dictionary_set(dict, key, str); \
|
||||
prop_object_release(str); \
|
||||
\
|
||||
return (rv); \
|
||||
}
|
||||
|
||||
TEMPLATE(,)
|
||||
TEMPLATE(_nocopy,const)
|
||||
|
||||
#undef TEMPLATE
|
||||
|
||||
bool
|
||||
prop_dictionary_set_and_rel(prop_dictionary_t dict, const char *key,
|
||||
prop_object_t po)
|
||||
{
|
||||
bool ret;
|
||||
if (po == NULL)
|
||||
return false;
|
||||
ret = prop_dictionary_set(dict, key, po);
|
||||
prop_object_release(po);
|
||||
return ret;
|
||||
}
|
||||
159
lib/external/portableproplib/prop_ingest.c
vendored
Normal file
159
lib/external/portableproplib/prop_ingest.c
vendored
Normal file
@@ -0,0 +1,159 @@
|
||||
/* $NetBSD: prop_ingest.c,v 1.5 2014/09/05 05:19:24 matt Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2006 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Jason R. Thorpe.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "prop_object_impl.h"
|
||||
#include <prop/proplib.h>
|
||||
|
||||
struct _prop_ingest_context {
|
||||
prop_ingest_error_t pic_error;
|
||||
prop_type_t pic_type;
|
||||
const char * pic_key;
|
||||
void * pic_private;
|
||||
};
|
||||
|
||||
/*
|
||||
* prop_ingest_context_alloc --
|
||||
* Allocate and initialize an ingest context.
|
||||
*/
|
||||
prop_ingest_context_t
|
||||
prop_ingest_context_alloc(void *xprivate)
|
||||
{
|
||||
prop_ingest_context_t ctx;
|
||||
|
||||
ctx = _PROP_MALLOC(sizeof(*ctx), M_TEMP);
|
||||
if (ctx != NULL) {
|
||||
ctx->pic_error = PROP_INGEST_ERROR_NO_ERROR;
|
||||
ctx->pic_type = PROP_TYPE_UNKNOWN;
|
||||
ctx->pic_key = NULL;
|
||||
ctx->pic_private = xprivate;
|
||||
}
|
||||
return (ctx);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_ingest_context_free --
|
||||
* Free an ingest context.
|
||||
*/
|
||||
void
|
||||
prop_ingest_context_free(prop_ingest_context_t ctx)
|
||||
{
|
||||
|
||||
_PROP_FREE(ctx, M_TEMP);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_ingest_context_error --
|
||||
* Get the error code from an ingest context.
|
||||
*/
|
||||
prop_ingest_error_t
|
||||
prop_ingest_context_error(prop_ingest_context_t ctx)
|
||||
{
|
||||
|
||||
return (ctx->pic_error);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_ingest_context_type --
|
||||
* Return the type of last object visisted by an ingest context.
|
||||
*/
|
||||
prop_type_t
|
||||
prop_ingest_context_type(prop_ingest_context_t ctx)
|
||||
{
|
||||
|
||||
return (ctx->pic_type);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_ingest_context_key --
|
||||
* Return the last key looked up by an ingest context.
|
||||
*/
|
||||
const char *
|
||||
prop_ingest_context_key(prop_ingest_context_t ctx)
|
||||
{
|
||||
|
||||
return (ctx->pic_key);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_ingest_context_private --
|
||||
* Return the caller-private data associated with an ingest context.
|
||||
*/
|
||||
void *
|
||||
prop_ingest_context_private(prop_ingest_context_t ctx)
|
||||
{
|
||||
|
||||
return (ctx->pic_private);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_dictionary_ingest --
|
||||
* Ingest a dictionary using handlers for each object to translate
|
||||
* into an arbitrary binary format.
|
||||
*/
|
||||
bool
|
||||
prop_dictionary_ingest(prop_dictionary_t dict,
|
||||
const prop_ingest_table_entry rules[],
|
||||
prop_ingest_context_t ctx)
|
||||
{
|
||||
const prop_ingest_table_entry *pite;
|
||||
prop_object_t obj;
|
||||
|
||||
ctx->pic_error = PROP_INGEST_ERROR_NO_ERROR;
|
||||
|
||||
for (pite = rules; pite->pite_key != NULL; pite++) {
|
||||
ctx->pic_key = pite->pite_key;
|
||||
obj = prop_dictionary_get(dict, pite->pite_key);
|
||||
ctx->pic_type = prop_object_type(obj);
|
||||
if (obj == NULL) {
|
||||
if (pite->pite_flags & PROP_INGEST_FLAG_OPTIONAL) {
|
||||
if ((*pite->pite_handler)(ctx, NULL) == false) {
|
||||
ctx->pic_error =
|
||||
PROP_INGEST_ERROR_HANDLER_FAILED;
|
||||
return (false);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
ctx->pic_error = PROP_INGEST_ERROR_NO_KEY;
|
||||
return (false);
|
||||
}
|
||||
if (ctx->pic_type != pite->pite_type &&
|
||||
pite->pite_type != PROP_TYPE_UNKNOWN) {
|
||||
ctx->pic_error = PROP_INGEST_ERROR_WRONG_TYPE;
|
||||
return (false);
|
||||
}
|
||||
if ((*pite->pite_handler)(ctx, obj) == false) {
|
||||
ctx->pic_error = PROP_INGEST_ERROR_HANDLER_FAILED;
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
|
||||
return (true);
|
||||
}
|
||||
584
lib/external/portableproplib/prop_number.c
vendored
Normal file
584
lib/external/portableproplib/prop_number.c
vendored
Normal file
@@ -0,0 +1,584 @@
|
||||
/* $NetBSD: prop_number.c,v 1.27 2014/09/05 05:19:24 matt Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2006 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Jason R. Thorpe.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <prop/prop_number.h>
|
||||
#include "prop_object_impl.h"
|
||||
#include "prop_rb_impl.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
struct _prop_number_value {
|
||||
union {
|
||||
int64_t pnu_signed;
|
||||
uint64_t pnu_unsigned;
|
||||
} pnv_un;
|
||||
#define pnv_signed pnv_un.pnu_signed
|
||||
#define pnv_unsigned pnv_un.pnu_unsigned
|
||||
unsigned int pnv_is_unsigned :1,
|
||||
:31;
|
||||
};
|
||||
|
||||
struct _prop_number {
|
||||
struct _prop_object pn_obj;
|
||||
struct rb_node pn_link;
|
||||
struct _prop_number_value pn_value;
|
||||
};
|
||||
|
||||
_PROP_POOL_INIT(_prop_number_pool, sizeof(struct _prop_number), "propnmbr")
|
||||
|
||||
static _prop_object_free_rv_t
|
||||
_prop_number_free(prop_stack_t, prop_object_t *);
|
||||
static bool _prop_number_externalize(
|
||||
struct _prop_object_externalize_context *,
|
||||
void *);
|
||||
static _prop_object_equals_rv_t
|
||||
_prop_number_equals(prop_object_t, prop_object_t,
|
||||
void **, void **,
|
||||
prop_object_t *, prop_object_t *);
|
||||
|
||||
static void _prop_number_lock(void);
|
||||
static void _prop_number_unlock(void);
|
||||
|
||||
static const struct _prop_object_type _prop_object_type_number = {
|
||||
.pot_type = PROP_TYPE_NUMBER,
|
||||
.pot_free = _prop_number_free,
|
||||
.pot_extern = _prop_number_externalize,
|
||||
.pot_equals = _prop_number_equals,
|
||||
.pot_lock = _prop_number_lock,
|
||||
.pot_unlock = _prop_number_unlock,
|
||||
};
|
||||
|
||||
#define prop_object_is_number(x) \
|
||||
((x) != NULL && (x)->pn_obj.po_type == &_prop_object_type_number)
|
||||
|
||||
/*
|
||||
* Number objects are immutable, and we are likely to have many number
|
||||
* objects that have the same value. So, to save memory, we unique'ify
|
||||
* numbers so we only have one copy of each.
|
||||
*/
|
||||
|
||||
static int
|
||||
_prop_number_compare_values(const struct _prop_number_value *pnv1,
|
||||
const struct _prop_number_value *pnv2)
|
||||
{
|
||||
|
||||
/* Signed numbers are sorted before unsigned numbers. */
|
||||
|
||||
if (pnv1->pnv_is_unsigned) {
|
||||
if (! pnv2->pnv_is_unsigned)
|
||||
return (1);
|
||||
if (pnv1->pnv_unsigned < pnv2->pnv_unsigned)
|
||||
return (-1);
|
||||
if (pnv1->pnv_unsigned > pnv2->pnv_unsigned)
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (pnv2->pnv_is_unsigned)
|
||||
return (-1);
|
||||
if (pnv1->pnv_signed < pnv2->pnv_signed)
|
||||
return (-1);
|
||||
if (pnv1->pnv_signed > pnv2->pnv_signed)
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
/*ARGSUSED*/
|
||||
_prop_number_rb_compare_nodes(void *ctx _PROP_ARG_UNUSED,
|
||||
const void *n1, const void *n2)
|
||||
{
|
||||
const struct _prop_number *pn1 = n1;
|
||||
const struct _prop_number *pn2 = n2;
|
||||
|
||||
return _prop_number_compare_values(&pn1->pn_value, &pn2->pn_value);
|
||||
}
|
||||
|
||||
static int
|
||||
/*ARGSUSED*/
|
||||
_prop_number_rb_compare_key(void *ctx _PROP_ARG_UNUSED,
|
||||
const void *n, const void *v)
|
||||
{
|
||||
const struct _prop_number *pn = n;
|
||||
const struct _prop_number_value *pnv = v;
|
||||
|
||||
return _prop_number_compare_values(&pn->pn_value, pnv);
|
||||
}
|
||||
|
||||
static const rb_tree_ops_t _prop_number_rb_tree_ops = {
|
||||
.rbto_compare_nodes = _prop_number_rb_compare_nodes,
|
||||
.rbto_compare_key = _prop_number_rb_compare_key,
|
||||
.rbto_node_offset = offsetof(struct _prop_number, pn_link),
|
||||
.rbto_context = NULL
|
||||
};
|
||||
|
||||
static struct rb_tree _prop_number_tree;
|
||||
_PROP_MUTEX_DECL_STATIC(_prop_number_tree_mutex)
|
||||
|
||||
/* ARGSUSED */
|
||||
static _prop_object_free_rv_t
|
||||
_prop_number_free(prop_stack_t stack, prop_object_t *obj)
|
||||
{
|
||||
prop_number_t pn = *obj;
|
||||
|
||||
_prop_rb_tree_remove_node(&_prop_number_tree, pn);
|
||||
|
||||
_PROP_POOL_PUT(_prop_number_pool, pn);
|
||||
|
||||
return (_PROP_OBJECT_FREE_DONE);
|
||||
}
|
||||
|
||||
_PROP_ONCE_DECL(_prop_number_init_once)
|
||||
|
||||
static int
|
||||
_prop_number_init(void)
|
||||
{
|
||||
|
||||
_PROP_MUTEX_INIT(_prop_number_tree_mutex);
|
||||
_prop_rb_tree_init(&_prop_number_tree, &_prop_number_rb_tree_ops);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
_prop_number_lock(void)
|
||||
{
|
||||
/* XXX: init necessary? */
|
||||
_PROP_ONCE_RUN(_prop_number_init_once, _prop_number_init);
|
||||
_PROP_MUTEX_LOCK(_prop_number_tree_mutex);
|
||||
}
|
||||
|
||||
static void
|
||||
_prop_number_unlock(void)
|
||||
{
|
||||
_PROP_MUTEX_UNLOCK(_prop_number_tree_mutex);
|
||||
}
|
||||
|
||||
static bool
|
||||
_prop_number_externalize(struct _prop_object_externalize_context *ctx,
|
||||
void *v)
|
||||
{
|
||||
prop_number_t pn = v;
|
||||
char tmpstr[32];
|
||||
|
||||
/*
|
||||
* For unsigned numbers, we output in hex. For signed numbers,
|
||||
* we output in decimal.
|
||||
*/
|
||||
if (pn->pn_value.pnv_is_unsigned)
|
||||
snprintf(tmpstr, sizeof(tmpstr), "%" PRIu64,
|
||||
pn->pn_value.pnv_unsigned);
|
||||
else
|
||||
snprintf(tmpstr, sizeof(tmpstr), "%" PRIi64,
|
||||
pn->pn_value.pnv_signed);
|
||||
|
||||
if (_prop_object_externalize_start_tag(ctx, "integer") == false ||
|
||||
_prop_object_externalize_append_cstring(ctx, tmpstr) == false ||
|
||||
_prop_object_externalize_end_tag(ctx, "integer") == false)
|
||||
return (false);
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static _prop_object_equals_rv_t
|
||||
_prop_number_equals(prop_object_t v1, prop_object_t v2,
|
||||
void **stored_pointer1, void **stored_pointer2,
|
||||
prop_object_t *next_obj1, prop_object_t *next_obj2)
|
||||
{
|
||||
prop_number_t num1 = v1;
|
||||
prop_number_t num2 = v2;
|
||||
|
||||
/*
|
||||
* There is only ever one copy of a number object at any given
|
||||
* time, so we can reduce this to a simple pointer equality check
|
||||
* in the common case.
|
||||
*/
|
||||
if (num1 == num2)
|
||||
return (_PROP_OBJECT_EQUALS_TRUE);
|
||||
|
||||
/*
|
||||
* If the numbers are the same signed-ness, then we know they
|
||||
* cannot be equal because they would have had pointer equality.
|
||||
*/
|
||||
if (num1->pn_value.pnv_is_unsigned == num2->pn_value.pnv_is_unsigned)
|
||||
return (_PROP_OBJECT_EQUALS_FALSE);
|
||||
|
||||
/*
|
||||
* We now have one signed value and one unsigned value. We can
|
||||
* compare them iff:
|
||||
* - The unsigned value is not larger than the signed value
|
||||
* can represent.
|
||||
* - The signed value is not smaller than the unsigned value
|
||||
* can represent.
|
||||
*/
|
||||
if (num1->pn_value.pnv_is_unsigned) {
|
||||
/*
|
||||
* num1 is unsigned and num2 is signed.
|
||||
*/
|
||||
if (num1->pn_value.pnv_unsigned > INT64_MAX)
|
||||
return (_PROP_OBJECT_EQUALS_FALSE);
|
||||
if (num2->pn_value.pnv_signed < 0)
|
||||
return (_PROP_OBJECT_EQUALS_FALSE);
|
||||
} else {
|
||||
/*
|
||||
* num1 is signed and num2 is unsigned.
|
||||
*/
|
||||
if (num1->pn_value.pnv_signed < 0)
|
||||
return (_PROP_OBJECT_EQUALS_FALSE);
|
||||
if (num2->pn_value.pnv_unsigned > INT64_MAX)
|
||||
return (_PROP_OBJECT_EQUALS_FALSE);
|
||||
}
|
||||
|
||||
if (num1->pn_value.pnv_signed == num2->pn_value.pnv_signed)
|
||||
return _PROP_OBJECT_EQUALS_TRUE;
|
||||
else
|
||||
return _PROP_OBJECT_EQUALS_FALSE;
|
||||
}
|
||||
|
||||
static prop_number_t
|
||||
_prop_number_alloc(const struct _prop_number_value *pnv)
|
||||
{
|
||||
prop_number_t opn, pn, rpn;
|
||||
|
||||
_PROP_ONCE_RUN(_prop_number_init_once, _prop_number_init);
|
||||
|
||||
/*
|
||||
* Check to see if this already exists in the tree. If it does,
|
||||
* we just retain it and return it.
|
||||
*/
|
||||
_PROP_MUTEX_LOCK(_prop_number_tree_mutex);
|
||||
opn = _prop_rb_tree_find(&_prop_number_tree, pnv);
|
||||
if (opn != NULL) {
|
||||
prop_object_retain(opn);
|
||||
_PROP_MUTEX_UNLOCK(_prop_number_tree_mutex);
|
||||
return (opn);
|
||||
}
|
||||
_PROP_MUTEX_UNLOCK(_prop_number_tree_mutex);
|
||||
|
||||
/*
|
||||
* Not in the tree. Create it now.
|
||||
*/
|
||||
|
||||
pn = _PROP_POOL_GET(_prop_number_pool);
|
||||
if (pn == NULL)
|
||||
return (NULL);
|
||||
|
||||
_prop_object_init(&pn->pn_obj, &_prop_object_type_number);
|
||||
|
||||
pn->pn_value = *pnv;
|
||||
|
||||
/*
|
||||
* We dropped the mutex when we allocated the new object, so
|
||||
* we have to check again if it is in the tree.
|
||||
*/
|
||||
_PROP_MUTEX_LOCK(_prop_number_tree_mutex);
|
||||
opn = _prop_rb_tree_find(&_prop_number_tree, pnv);
|
||||
if (opn != NULL) {
|
||||
prop_object_retain(opn);
|
||||
_PROP_MUTEX_UNLOCK(_prop_number_tree_mutex);
|
||||
_PROP_POOL_PUT(_prop_number_pool, pn);
|
||||
return (opn);
|
||||
}
|
||||
rpn = _prop_rb_tree_insert_node(&_prop_number_tree, pn);
|
||||
_PROP_ASSERT(rpn == pn);
|
||||
_PROP_MUTEX_UNLOCK(_prop_number_tree_mutex);
|
||||
return (rpn);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_number_create_integer --
|
||||
* Create a prop_number_t and initialize it with the
|
||||
* provided integer value.
|
||||
*/
|
||||
prop_number_t
|
||||
prop_number_create_integer(int64_t val)
|
||||
{
|
||||
struct _prop_number_value pnv;
|
||||
|
||||
memset(&pnv, 0, sizeof(pnv));
|
||||
pnv.pnv_signed = val;
|
||||
pnv.pnv_is_unsigned = false;
|
||||
|
||||
return (_prop_number_alloc(&pnv));
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_number_create_unsigned_integer --
|
||||
* Create a prop_number_t and initialize it with the
|
||||
* provided unsigned integer value.
|
||||
*/
|
||||
prop_number_t
|
||||
prop_number_create_unsigned_integer(uint64_t val)
|
||||
{
|
||||
struct _prop_number_value pnv;
|
||||
|
||||
memset(&pnv, 0, sizeof(pnv));
|
||||
pnv.pnv_unsigned = val;
|
||||
pnv.pnv_is_unsigned = true;
|
||||
|
||||
return (_prop_number_alloc(&pnv));
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_number_copy --
|
||||
* Copy a prop_number_t.
|
||||
*/
|
||||
prop_number_t
|
||||
prop_number_copy(prop_number_t opn)
|
||||
{
|
||||
|
||||
if (! prop_object_is_number(opn))
|
||||
return (NULL);
|
||||
|
||||
/*
|
||||
* Because we only ever allocate one object for any given
|
||||
* value, this can be reduced to a simple retain operation.
|
||||
*/
|
||||
prop_object_retain(opn);
|
||||
return (opn);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_number_unsigned --
|
||||
* Returns true if the prop_number_t has an unsigned value.
|
||||
*/
|
||||
bool
|
||||
prop_number_unsigned(prop_number_t pn)
|
||||
{
|
||||
|
||||
return (pn->pn_value.pnv_is_unsigned);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_number_size --
|
||||
* Return the size, in bits, required to hold the value of
|
||||
* the specified number.
|
||||
*/
|
||||
int
|
||||
prop_number_size(prop_number_t pn)
|
||||
{
|
||||
struct _prop_number_value *pnv;
|
||||
|
||||
if (! prop_object_is_number(pn))
|
||||
return (0);
|
||||
|
||||
pnv = &pn->pn_value;
|
||||
|
||||
if (pnv->pnv_is_unsigned) {
|
||||
if (pnv->pnv_unsigned > UINT32_MAX)
|
||||
return (64);
|
||||
if (pnv->pnv_unsigned > UINT16_MAX)
|
||||
return (32);
|
||||
if (pnv->pnv_unsigned > UINT8_MAX)
|
||||
return (16);
|
||||
return (8);
|
||||
}
|
||||
|
||||
if (pnv->pnv_signed > INT32_MAX || pnv->pnv_signed < INT32_MIN)
|
||||
return (64);
|
||||
if (pnv->pnv_signed > INT16_MAX || pnv->pnv_signed < INT16_MIN)
|
||||
return (32);
|
||||
if (pnv->pnv_signed > INT8_MAX || pnv->pnv_signed < INT8_MIN)
|
||||
return (16);
|
||||
return (8);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_number_integer_value --
|
||||
* Get the integer value of a prop_number_t.
|
||||
*/
|
||||
int64_t
|
||||
prop_number_integer_value(prop_number_t pn)
|
||||
{
|
||||
|
||||
/*
|
||||
* XXX Impossible to distinguish between "not a prop_number_t"
|
||||
* XXX and "prop_number_t has a value of 0".
|
||||
*/
|
||||
if (! prop_object_is_number(pn))
|
||||
return (0);
|
||||
|
||||
return (pn->pn_value.pnv_signed);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_number_unsigned_integer_value --
|
||||
* Get the unsigned integer value of a prop_number_t.
|
||||
*/
|
||||
uint64_t
|
||||
prop_number_unsigned_integer_value(prop_number_t pn)
|
||||
{
|
||||
|
||||
/*
|
||||
* XXX Impossible to distinguish between "not a prop_number_t"
|
||||
* XXX and "prop_number_t has a value of 0".
|
||||
*/
|
||||
if (! prop_object_is_number(pn))
|
||||
return (0);
|
||||
|
||||
return (pn->pn_value.pnv_unsigned);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_number_equals --
|
||||
* Return true if two numbers are equivalent.
|
||||
*/
|
||||
bool
|
||||
prop_number_equals(prop_number_t num1, prop_number_t num2)
|
||||
{
|
||||
if (!prop_object_is_number(num1) || !prop_object_is_number(num2))
|
||||
return (false);
|
||||
|
||||
return (prop_object_equals(num1, num2));
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_number_equals_integer --
|
||||
* Return true if the number is equivalent to the specified integer.
|
||||
*/
|
||||
bool
|
||||
prop_number_equals_integer(prop_number_t pn, int64_t val)
|
||||
{
|
||||
|
||||
if (! prop_object_is_number(pn))
|
||||
return (false);
|
||||
|
||||
if (pn->pn_value.pnv_is_unsigned &&
|
||||
(pn->pn_value.pnv_unsigned > INT64_MAX || val < 0))
|
||||
return (false);
|
||||
|
||||
return (pn->pn_value.pnv_signed == val);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_number_equals_unsigned_integer --
|
||||
* Return true if the number is equivalent to the specified
|
||||
* unsigned integer.
|
||||
*/
|
||||
bool
|
||||
prop_number_equals_unsigned_integer(prop_number_t pn, uint64_t val)
|
||||
{
|
||||
|
||||
if (! prop_object_is_number(pn))
|
||||
return (false);
|
||||
|
||||
if (! pn->pn_value.pnv_is_unsigned &&
|
||||
(pn->pn_value.pnv_signed < 0 || val > INT64_MAX))
|
||||
return (false);
|
||||
|
||||
return (pn->pn_value.pnv_unsigned == val);
|
||||
}
|
||||
|
||||
static bool
|
||||
_prop_number_internalize_unsigned(struct _prop_object_internalize_context *ctx,
|
||||
struct _prop_number_value *pnv)
|
||||
{
|
||||
char *cp;
|
||||
|
||||
_PROP_ASSERT(/*CONSTCOND*/sizeof(unsigned long long) ==
|
||||
sizeof(uint64_t));
|
||||
|
||||
errno = 0;
|
||||
pnv->pnv_unsigned = (uint64_t) strtoull(ctx->poic_cp, &cp, 0);
|
||||
if (pnv->pnv_unsigned == UINT64_MAX && errno == ERANGE)
|
||||
return (false);
|
||||
|
||||
pnv->pnv_is_unsigned = true;
|
||||
ctx->poic_cp = cp;
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
static bool
|
||||
_prop_number_internalize_signed(struct _prop_object_internalize_context *ctx,
|
||||
struct _prop_number_value *pnv)
|
||||
{
|
||||
char *cp;
|
||||
|
||||
_PROP_ASSERT(/*CONSTCOND*/sizeof(long long) == sizeof(int64_t));
|
||||
|
||||
errno = 0;
|
||||
pnv->pnv_signed = (int64_t) strtoll(ctx->poic_cp, &cp, 0);
|
||||
if ((pnv->pnv_signed == INT64_MAX || pnv->pnv_signed == INT64_MIN) &&
|
||||
errno == ERANGE)
|
||||
return (false);
|
||||
|
||||
pnv->pnv_is_unsigned = false;
|
||||
ctx->poic_cp = cp;
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
/*
|
||||
* _prop_number_internalize --
|
||||
* Parse a <number>...</number> and return the object created from
|
||||
* the external representation.
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
bool
|
||||
_prop_number_internalize(prop_stack_t stack, prop_object_t *obj,
|
||||
struct _prop_object_internalize_context *ctx)
|
||||
{
|
||||
struct _prop_number_value pnv;
|
||||
|
||||
memset(&pnv, 0, sizeof(pnv));
|
||||
|
||||
/* No attributes, no empty elements. */
|
||||
if (ctx->poic_tagattr != NULL || ctx->poic_is_empty_element)
|
||||
return (true);
|
||||
|
||||
/*
|
||||
* If the first character is '-', then we treat as signed.
|
||||
* If the first two characters are "0x" (i.e. the number is
|
||||
* in hex), then we treat as unsigned. Otherwise, we try
|
||||
* signed first, and if that fails (presumably due to ERANGE),
|
||||
* then we switch to unsigned.
|
||||
*/
|
||||
if (ctx->poic_cp[0] == '-') {
|
||||
if (_prop_number_internalize_signed(ctx, &pnv) == false)
|
||||
return (true);
|
||||
} else if (ctx->poic_cp[0] == '0' && ctx->poic_cp[1] == 'x') {
|
||||
if (_prop_number_internalize_unsigned(ctx, &pnv) == false)
|
||||
return (true);
|
||||
} else {
|
||||
if (_prop_number_internalize_signed(ctx, &pnv) == false &&
|
||||
_prop_number_internalize_unsigned(ctx, &pnv) == false)
|
||||
return (true);
|
||||
}
|
||||
|
||||
if (_prop_object_internalize_find_tag(ctx, "integer",
|
||||
_PROP_TAG_TYPE_END) == false)
|
||||
return (true);
|
||||
|
||||
*obj = _prop_number_alloc(&pnv);
|
||||
return (true);
|
||||
}
|
||||
1242
lib/external/portableproplib/prop_object.c
vendored
Normal file
1242
lib/external/portableproplib/prop_object.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
336
lib/external/portableproplib/prop_object_impl.h
vendored
Normal file
336
lib/external/portableproplib/prop_object_impl.h
vendored
Normal file
@@ -0,0 +1,336 @@
|
||||
/* $NetBSD: prop_object_impl.h,v 1.31 2012/07/27 09:10:59 pooka Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2006 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Jason R. Thorpe.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _PROPLIB_PROP_OBJECT_IMPL_H_
|
||||
#define _PROPLIB_PROP_OBJECT_IMPL_H_
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "prop_stack.h"
|
||||
|
||||
struct _prop_object_externalize_context {
|
||||
char * poec_buf; /* string buffer */
|
||||
size_t poec_capacity; /* capacity of buffer */
|
||||
size_t poec_len; /* current length of string */
|
||||
unsigned int poec_depth; /* nesting depth */
|
||||
};
|
||||
|
||||
bool _prop_object_externalize_start_tag(
|
||||
struct _prop_object_externalize_context *,
|
||||
const char *);
|
||||
bool _prop_object_externalize_end_tag(
|
||||
struct _prop_object_externalize_context *,
|
||||
const char *);
|
||||
bool _prop_object_externalize_empty_tag(
|
||||
struct _prop_object_externalize_context *,
|
||||
const char *);
|
||||
bool _prop_object_externalize_append_cstring(
|
||||
struct _prop_object_externalize_context *,
|
||||
const char *);
|
||||
bool _prop_object_externalize_append_encoded_cstring(
|
||||
struct _prop_object_externalize_context *,
|
||||
const char *);
|
||||
bool _prop_object_externalize_append_char(
|
||||
struct _prop_object_externalize_context *,
|
||||
unsigned char);
|
||||
bool _prop_object_externalize_header(
|
||||
struct _prop_object_externalize_context *);
|
||||
bool _prop_object_externalize_footer(
|
||||
struct _prop_object_externalize_context *);
|
||||
|
||||
struct _prop_object_externalize_context *
|
||||
_prop_object_externalize_context_alloc(void);
|
||||
void _prop_object_externalize_context_free(
|
||||
struct _prop_object_externalize_context *);
|
||||
|
||||
typedef enum {
|
||||
_PROP_TAG_TYPE_START, /* e.g. <dict> */
|
||||
_PROP_TAG_TYPE_END, /* e.g. </dict> */
|
||||
_PROP_TAG_TYPE_EITHER
|
||||
} _prop_tag_type_t;
|
||||
|
||||
struct _prop_object_internalize_context {
|
||||
const char *poic_xml;
|
||||
const char *poic_cp;
|
||||
|
||||
const char *poic_tag_start;
|
||||
|
||||
const char *poic_tagname;
|
||||
size_t poic_tagname_len;
|
||||
const char *poic_tagattr;
|
||||
size_t poic_tagattr_len;
|
||||
const char *poic_tagattrval;
|
||||
size_t poic_tagattrval_len;
|
||||
|
||||
bool poic_is_empty_element;
|
||||
_prop_tag_type_t poic_tag_type;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
_PROP_OBJECT_FREE_DONE,
|
||||
_PROP_OBJECT_FREE_RECURSE,
|
||||
_PROP_OBJECT_FREE_FAILED
|
||||
} _prop_object_free_rv_t;
|
||||
|
||||
typedef enum {
|
||||
_PROP_OBJECT_EQUALS_FALSE,
|
||||
_PROP_OBJECT_EQUALS_TRUE,
|
||||
_PROP_OBJECT_EQUALS_RECURSE
|
||||
} _prop_object_equals_rv_t;
|
||||
|
||||
#define _PROP_EOF(c) ((c) == '\0')
|
||||
#define _PROP_ISSPACE(c) \
|
||||
((c) == ' ' || (c) == '\t' || (c) == '\n' || (c) == '\r')
|
||||
|
||||
#define _PROP_TAG_MATCH(ctx, t) \
|
||||
_prop_object_internalize_match((ctx)->poic_tagname, \
|
||||
(ctx)->poic_tagname_len, \
|
||||
(t), strlen(t))
|
||||
|
||||
#define _PROP_TAGATTR_MATCH(ctx, a) \
|
||||
_prop_object_internalize_match((ctx)->poic_tagattr, \
|
||||
(ctx)->poic_tagattr_len, \
|
||||
(a), strlen(a))
|
||||
|
||||
#define _PROP_TAGATTRVAL_MATCH(ctx, a) \
|
||||
_prop_object_internalize_match((ctx)->poic_tagattrval, \
|
||||
(ctx)->poic_tagattrval_len,\
|
||||
(a), strlen(a))
|
||||
|
||||
bool _prop_object_internalize_find_tag(
|
||||
struct _prop_object_internalize_context *,
|
||||
const char *, _prop_tag_type_t);
|
||||
bool _prop_object_internalize_match(const char *, size_t,
|
||||
const char *, size_t);
|
||||
prop_object_t _prop_object_internalize_by_tag(
|
||||
struct _prop_object_internalize_context *);
|
||||
bool _prop_object_internalize_decode_string(
|
||||
struct _prop_object_internalize_context *,
|
||||
char *, size_t, size_t *, const char **);
|
||||
prop_object_t _prop_generic_internalize(const char *, const char *);
|
||||
|
||||
struct _prop_object_internalize_context *
|
||||
_prop_object_internalize_context_alloc(const char *);
|
||||
void _prop_object_internalize_context_free(
|
||||
struct _prop_object_internalize_context *);
|
||||
|
||||
bool _prop_object_externalize_write_file(const char *,
|
||||
const char *, size_t, bool);
|
||||
|
||||
struct _prop_object_internalize_mapped_file {
|
||||
char * poimf_xml;
|
||||
size_t poimf_mapsize;
|
||||
};
|
||||
|
||||
struct _prop_object_internalize_mapped_file *
|
||||
_prop_object_internalize_map_file(const char *);
|
||||
void _prop_object_internalize_unmap_file(
|
||||
struct _prop_object_internalize_mapped_file *);
|
||||
|
||||
typedef bool (*prop_object_internalizer_t)(prop_stack_t, prop_object_t *,
|
||||
struct _prop_object_internalize_context *);
|
||||
typedef bool (*prop_object_internalizer_continue_t)(prop_stack_t,
|
||||
prop_object_t *,
|
||||
struct _prop_object_internalize_context *,
|
||||
void *, prop_object_t);
|
||||
|
||||
/* These are here because they're required by shared code. */
|
||||
bool _prop_array_internalize(prop_stack_t, prop_object_t *,
|
||||
struct _prop_object_internalize_context *);
|
||||
bool _prop_bool_internalize(prop_stack_t, prop_object_t *,
|
||||
struct _prop_object_internalize_context *);
|
||||
bool _prop_data_internalize(prop_stack_t, prop_object_t *,
|
||||
struct _prop_object_internalize_context *);
|
||||
bool _prop_dictionary_internalize(prop_stack_t, prop_object_t *,
|
||||
struct _prop_object_internalize_context *);
|
||||
bool _prop_number_internalize(prop_stack_t, prop_object_t *,
|
||||
struct _prop_object_internalize_context *);
|
||||
bool _prop_string_internalize(prop_stack_t, prop_object_t *,
|
||||
struct _prop_object_internalize_context *);
|
||||
|
||||
struct _prop_object_type {
|
||||
/* type indicator */
|
||||
uint32_t pot_type;
|
||||
/* func to free object */
|
||||
_prop_object_free_rv_t
|
||||
(*pot_free)(prop_stack_t, prop_object_t *);
|
||||
/*
|
||||
* func to free the child returned by pot_free with stack == NULL.
|
||||
*
|
||||
* Must be implemented if pot_free can return anything other than
|
||||
* _PROP_OBJECT_FREE_DONE.
|
||||
*/
|
||||
void (*pot_emergency_free)(prop_object_t);
|
||||
/* func to externalize object */
|
||||
bool (*pot_extern)(struct _prop_object_externalize_context *,
|
||||
void *);
|
||||
/* func to test quality */
|
||||
_prop_object_equals_rv_t
|
||||
(*pot_equals)(prop_object_t, prop_object_t,
|
||||
void **, void **,
|
||||
prop_object_t *, prop_object_t *);
|
||||
/*
|
||||
* func to finish equality iteration.
|
||||
*
|
||||
* Must be implemented if pot_equals can return
|
||||
* _PROP_OBJECT_EQUALS_RECURSE
|
||||
*/
|
||||
void (*pot_equals_finish)(prop_object_t, prop_object_t);
|
||||
void (*pot_lock)(void);
|
||||
void (*pot_unlock)(void);
|
||||
};
|
||||
|
||||
struct _prop_object {
|
||||
const struct _prop_object_type *po_type;/* type descriptor */
|
||||
uint32_t po_refcnt; /* reference count */
|
||||
};
|
||||
|
||||
void _prop_object_init(struct _prop_object *,
|
||||
const struct _prop_object_type *);
|
||||
void _prop_object_fini(struct _prop_object *);
|
||||
|
||||
struct _prop_object_iterator {
|
||||
prop_object_t (*pi_next_object)(void *);
|
||||
void (*pi_reset)(void *);
|
||||
prop_object_t pi_obj;
|
||||
uint32_t pi_version;
|
||||
};
|
||||
|
||||
#define _PROP_NOTHREAD_ONCE_DECL(x) static bool x = false;
|
||||
#define _PROP_NOTHREAD_ONCE_RUN(x,f) \
|
||||
do { \
|
||||
if ((x) == false) { \
|
||||
f(); \
|
||||
x = true; \
|
||||
} \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
/*
|
||||
* proplib in user space...
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define _PROP_ASSERT(x) /*LINTED*/assert(x)
|
||||
|
||||
#define _PROP_MALLOC(s, t) malloc((s))
|
||||
#define _PROP_CALLOC(s, t) calloc(1, (s))
|
||||
#define _PROP_REALLOC(v, s, t) realloc((v), (s))
|
||||
#define _PROP_FREE(v, t) free((v))
|
||||
|
||||
#define _PROP_POOL_GET(p) malloc((p))
|
||||
#define _PROP_POOL_PUT(p, v) free((v))
|
||||
|
||||
#define _PROP_POOL_INIT(p, s, d) static const size_t p = s;
|
||||
|
||||
#define _PROP_MALLOC_DEFINE(t, s, l) /* nothing */
|
||||
|
||||
/*
|
||||
* Use pthread mutexes everywhere else.
|
||||
*/
|
||||
#include <pthread.h>
|
||||
#define _PROP_MUTEX_DECL_STATIC(x) static pthread_mutex_t x;
|
||||
#define _PROP_MUTEX_INIT(x) pthread_mutex_init(&(x), NULL)
|
||||
#define _PROP_MUTEX_LOCK(x) pthread_mutex_lock(&(x))
|
||||
#define _PROP_MUTEX_UNLOCK(x) pthread_mutex_unlock(&(x))
|
||||
|
||||
#define _PROP_RWLOCK_DECL(x) pthread_rwlock_t x ;
|
||||
#define _PROP_RWLOCK_INIT(x) pthread_rwlock_init(&(x), NULL)
|
||||
#define _PROP_RWLOCK_RDLOCK(x) pthread_rwlock_rdlock(&(x))
|
||||
#define _PROP_RWLOCK_WRLOCK(x) pthread_rwlock_wrlock(&(x))
|
||||
#define _PROP_RWLOCK_UNLOCK(x) pthread_rwlock_unlock(&(x))
|
||||
#define _PROP_RWLOCK_DESTROY(x) pthread_rwlock_destroy(&(x))
|
||||
|
||||
#define _PROP_ONCE_DECL(x) \
|
||||
static pthread_once_t x = PTHREAD_ONCE_INIT;
|
||||
#define _PROP_ONCE_RUN(x,f) pthread_once(&(x),(void(*)(void))f)
|
||||
|
||||
#ifndef HAVE_ATOMICS /* NO ATOMIC SUPPORT, USE A MUTEX */
|
||||
|
||||
#define _PROP_NEED_REFCNT_MTX
|
||||
#define _PROP_ATOMIC_INC32(x) \
|
||||
do { \
|
||||
pthread_mutex_lock(&_prop_refcnt_mtx); \
|
||||
(*(x))++; \
|
||||
pthread_mutex_unlock(&_prop_refcnt_mtx); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
#define _PROP_ATOMIC_DEC32(x) \
|
||||
do { \
|
||||
pthread_mutex_lock(&_prop_refcnt_mtx); \
|
||||
(*(x))--; \
|
||||
pthread_mutex_unlock(&_prop_refcnt_mtx); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
#define _PROP_ATOMIC_INC32_NV(x, v) \
|
||||
do { \
|
||||
pthread_mutex_lock(&_prop_refcnt_mtx); \
|
||||
v = ++(*(x)); \
|
||||
pthread_mutex_unlock(&_prop_refcnt_mtx); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
#define _PROP_ATOMIC_DEC32_NV(x, v) \
|
||||
do { \
|
||||
pthread_mutex_lock(&_prop_refcnt_mtx); \
|
||||
v = --(*(x)); \
|
||||
pthread_mutex_unlock(&_prop_refcnt_mtx); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#else /* GCC ATOMIC BUILTINS */
|
||||
|
||||
#define _PROP_ATOMIC_INC32(x) \
|
||||
do { \
|
||||
(void)__sync_fetch_and_add(x, 1); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define _PROP_ATOMIC_DEC32(x) \
|
||||
do { \
|
||||
(void)__sync_fetch_and_sub(x, 1); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define _PROP_ATOMIC_INC32_NV(x, v) \
|
||||
do { \
|
||||
v = __sync_add_and_fetch(x, 1); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define _PROP_ATOMIC_DEC32_NV(x, v) \
|
||||
do { \
|
||||
v = __sync_sub_and_fetch(x, 1); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#endif /* !HAVE_ATOMICS */
|
||||
|
||||
/*
|
||||
* Language features.
|
||||
*/
|
||||
#define _PROP_ARG_UNUSED __attribute__((unused))
|
||||
|
||||
#endif /* _PROPLIB_PROP_OBJECT_IMPL_H_ */
|
||||
46
lib/external/portableproplib/prop_rb_impl.h
vendored
Normal file
46
lib/external/portableproplib/prop_rb_impl.h
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
/* $NetBSD: prop_rb_impl.h,v 1.8 2010/09/25 01:42:38 matt Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2001 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Matt Thomas <matt@3am-software.com>.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _PROP_RB_IMPL_H_
|
||||
#define _PROP_RB_IMPL_H_
|
||||
|
||||
#include <rbtree.h>
|
||||
|
||||
/*
|
||||
* Define local names for common rb_tree functions.
|
||||
*/
|
||||
#define _prop_rb_tree_init rb_tree_init
|
||||
#define _prop_rb_tree_insert_node rb_tree_insert_node
|
||||
#define _prop_rb_tree_find rb_tree_find_node
|
||||
#define _prop_rb_tree_remove_node rb_tree_remove_node
|
||||
#define _prop_rb_tree_iterate rb_tree_iterate
|
||||
|
||||
#endif /* _PROP_RB_IMPL_H_*/
|
||||
118
lib/external/portableproplib/prop_stack.c
vendored
Normal file
118
lib/external/portableproplib/prop_stack.c
vendored
Normal file
@@ -0,0 +1,118 @@
|
||||
/* $NetBSD: prop_stack.c,v 1.2 2007/08/30 12:23:54 joerg Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2007 Joerg Sonnenberger <joerg@NetBSD.org>.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "prop_stack.h"
|
||||
#include "prop_object_impl.h"
|
||||
|
||||
void
|
||||
_prop_stack_init(prop_stack_t stack)
|
||||
{
|
||||
stack->used_intern_elems = 0;
|
||||
SLIST_INIT(&stack->extern_elems);
|
||||
}
|
||||
|
||||
bool
|
||||
_prop_stack_push(prop_stack_t stack, prop_object_t obj, void *data1,
|
||||
void *data2, void *data3)
|
||||
{
|
||||
struct _prop_stack_extern_elem *eelem;
|
||||
struct _prop_stack_intern_elem *ielem;
|
||||
|
||||
if (stack->used_intern_elems == PROP_STACK_INTERN_ELEMS) {
|
||||
eelem = _PROP_MALLOC(sizeof(*eelem), M_TEMP);
|
||||
|
||||
if (eelem == NULL)
|
||||
return false;
|
||||
|
||||
eelem->object = obj;
|
||||
eelem->object_data[0] = data1;
|
||||
eelem->object_data[1] = data2;
|
||||
eelem->object_data[2] = data3;
|
||||
|
||||
SLIST_INSERT_HEAD(&stack->extern_elems, eelem, stack_link);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
_PROP_ASSERT(stack->used_intern_elems < PROP_STACK_INTERN_ELEMS);
|
||||
_PROP_ASSERT(SLIST_EMPTY(&stack->extern_elems));
|
||||
|
||||
ielem = &stack->intern_elems[stack->used_intern_elems];
|
||||
ielem->object = obj;
|
||||
ielem->object_data[0] = data1;
|
||||
ielem->object_data[1] = data2;
|
||||
ielem->object_data[2] = data3;
|
||||
|
||||
++stack->used_intern_elems;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
_prop_stack_pop(prop_stack_t stack, prop_object_t *obj, void **data1,
|
||||
void **data2, void **data3)
|
||||
{
|
||||
struct _prop_stack_extern_elem *eelem;
|
||||
struct _prop_stack_intern_elem *ielem;
|
||||
|
||||
if (stack->used_intern_elems == 0)
|
||||
return false;
|
||||
|
||||
if ((eelem = SLIST_FIRST(&stack->extern_elems)) != NULL) {
|
||||
_PROP_ASSERT(stack->used_intern_elems == PROP_STACK_INTERN_ELEMS);
|
||||
|
||||
SLIST_REMOVE_HEAD(&stack->extern_elems, stack_link);
|
||||
if (obj)
|
||||
*obj = eelem->object;
|
||||
if (data1)
|
||||
*data1 = eelem->object_data[0];
|
||||
if (data2)
|
||||
*data2 = eelem->object_data[1];
|
||||
if (data3)
|
||||
*data3 = eelem->object_data[2];
|
||||
_PROP_FREE(eelem, M_TEMP);
|
||||
return true;
|
||||
}
|
||||
|
||||
--stack->used_intern_elems;
|
||||
ielem = &stack->intern_elems[stack->used_intern_elems];
|
||||
|
||||
if (obj)
|
||||
*obj = ielem->object;
|
||||
if (data1)
|
||||
*data1 = ielem->object_data[0];
|
||||
if (data2)
|
||||
*data2 = ielem->object_data[1];
|
||||
if (data3)
|
||||
*data3 = ielem->object_data[2];
|
||||
|
||||
return true;
|
||||
}
|
||||
64
lib/external/portableproplib/prop_stack.h
vendored
Normal file
64
lib/external/portableproplib/prop_stack.h
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
/* $NetBSD: prop_stack.h,v 1.2 2007/08/30 12:23:54 joerg Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2007 Joerg Sonnenberger <joerg@NetBSD.org>.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _PROP_STACK_H
|
||||
#define _PROP_STACK_H
|
||||
|
||||
#include <queue.h>
|
||||
#include <prop/prop_object.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
struct _prop_stack_intern_elem {
|
||||
prop_object_t object;
|
||||
void *object_data[3];
|
||||
};
|
||||
|
||||
struct _prop_stack_extern_elem {
|
||||
SLIST_ENTRY(_prop_stack_extern_elem) stack_link;
|
||||
prop_object_t object;
|
||||
void *object_data[3];
|
||||
};
|
||||
|
||||
#define PROP_STACK_INTERN_ELEMS 16
|
||||
|
||||
struct _prop_stack {
|
||||
struct _prop_stack_intern_elem intern_elems[PROP_STACK_INTERN_ELEMS];
|
||||
size_t used_intern_elems;
|
||||
SLIST_HEAD(, _prop_stack_extern_elem) extern_elems;
|
||||
};
|
||||
|
||||
typedef struct _prop_stack *prop_stack_t;
|
||||
|
||||
void _prop_stack_init(prop_stack_t);
|
||||
bool _prop_stack_push(prop_stack_t, prop_object_t, void *, void *, void *);
|
||||
bool _prop_stack_pop(prop_stack_t, prop_object_t *, void **, void **, void **);
|
||||
|
||||
#endif
|
||||
469
lib/external/portableproplib/prop_string.c
vendored
Normal file
469
lib/external/portableproplib/prop_string.c
vendored
Normal file
@@ -0,0 +1,469 @@
|
||||
/* $NetBSD: prop_string.c,v 1.12 2014/03/26 18:12:46 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2006 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Jason R. Thorpe.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <prop/prop_string.h>
|
||||
#include "prop_object_impl.h"
|
||||
|
||||
struct _prop_string {
|
||||
struct _prop_object ps_obj;
|
||||
union {
|
||||
char * psu_mutable;
|
||||
const char * psu_immutable;
|
||||
} ps_un;
|
||||
#define ps_mutable ps_un.psu_mutable
|
||||
#define ps_immutable ps_un.psu_immutable
|
||||
size_t ps_size; /* not including \0 */
|
||||
int ps_flags;
|
||||
};
|
||||
|
||||
#define PS_F_NOCOPY 0x01
|
||||
|
||||
_PROP_POOL_INIT(_prop_string_pool, sizeof(struct _prop_string), "propstng")
|
||||
|
||||
|
||||
static _prop_object_free_rv_t
|
||||
_prop_string_free(prop_stack_t, prop_object_t *);
|
||||
static bool _prop_string_externalize(
|
||||
struct _prop_object_externalize_context *,
|
||||
void *);
|
||||
static _prop_object_equals_rv_t
|
||||
_prop_string_equals(prop_object_t, prop_object_t,
|
||||
void **, void **,
|
||||
prop_object_t *, prop_object_t *);
|
||||
|
||||
static const struct _prop_object_type _prop_object_type_string = {
|
||||
.pot_type = PROP_TYPE_STRING,
|
||||
.pot_free = _prop_string_free,
|
||||
.pot_extern = _prop_string_externalize,
|
||||
.pot_equals = _prop_string_equals,
|
||||
};
|
||||
|
||||
#define prop_object_is_string(x) \
|
||||
((x) != NULL && (x)->ps_obj.po_type == &_prop_object_type_string)
|
||||
#define prop_string_contents(x) ((x)->ps_immutable ? (x)->ps_immutable : "")
|
||||
|
||||
/* ARGSUSED */
|
||||
static _prop_object_free_rv_t
|
||||
_prop_string_free(prop_stack_t stack, prop_object_t *obj)
|
||||
{
|
||||
prop_string_t ps = *obj;
|
||||
|
||||
if ((ps->ps_flags & PS_F_NOCOPY) == 0 && ps->ps_mutable != NULL)
|
||||
_PROP_FREE(ps->ps_mutable, M_PROP_STRING);
|
||||
_PROP_POOL_PUT(_prop_string_pool, ps);
|
||||
|
||||
return (_PROP_OBJECT_FREE_DONE);
|
||||
}
|
||||
|
||||
static bool
|
||||
_prop_string_externalize(struct _prop_object_externalize_context *ctx,
|
||||
void *v)
|
||||
{
|
||||
prop_string_t ps = v;
|
||||
|
||||
if (ps->ps_size == 0)
|
||||
return (_prop_object_externalize_empty_tag(ctx, "string"));
|
||||
|
||||
if (_prop_object_externalize_start_tag(ctx, "string") == false ||
|
||||
_prop_object_externalize_append_encoded_cstring(ctx,
|
||||
ps->ps_immutable) == false ||
|
||||
_prop_object_externalize_end_tag(ctx, "string") == false)
|
||||
return (false);
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static _prop_object_equals_rv_t
|
||||
_prop_string_equals(prop_object_t v1, prop_object_t v2,
|
||||
void **stored_pointer1, void **stored_pointer2,
|
||||
prop_object_t *next_obj1, prop_object_t *next_obj2)
|
||||
{
|
||||
prop_string_t str1 = v1;
|
||||
prop_string_t str2 = v2;
|
||||
|
||||
if (str1 == str2)
|
||||
return (_PROP_OBJECT_EQUALS_TRUE);
|
||||
if (str1->ps_size != str2->ps_size)
|
||||
return (_PROP_OBJECT_EQUALS_FALSE);
|
||||
if (strcmp(prop_string_contents(str1), prop_string_contents(str2)))
|
||||
return (_PROP_OBJECT_EQUALS_FALSE);
|
||||
else
|
||||
return (_PROP_OBJECT_EQUALS_TRUE);
|
||||
}
|
||||
|
||||
static prop_string_t
|
||||
_prop_string_alloc(void)
|
||||
{
|
||||
prop_string_t ps;
|
||||
|
||||
ps = _PROP_POOL_GET(_prop_string_pool);
|
||||
if (ps != NULL) {
|
||||
_prop_object_init(&ps->ps_obj, &_prop_object_type_string);
|
||||
|
||||
ps->ps_mutable = NULL;
|
||||
ps->ps_size = 0;
|
||||
ps->ps_flags = 0;
|
||||
}
|
||||
|
||||
return (ps);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_string_create --
|
||||
* Create an empty mutable string.
|
||||
*/
|
||||
prop_string_t
|
||||
prop_string_create(void)
|
||||
{
|
||||
|
||||
return (_prop_string_alloc());
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_string_create_cstring --
|
||||
* Create a string that contains a copy of the provided C string.
|
||||
*/
|
||||
prop_string_t
|
||||
prop_string_create_cstring(const char *str)
|
||||
{
|
||||
prop_string_t ps;
|
||||
char *cp;
|
||||
size_t len;
|
||||
|
||||
ps = _prop_string_alloc();
|
||||
if (ps != NULL) {
|
||||
len = strlen(str);
|
||||
cp = _PROP_MALLOC(len + 1, M_PROP_STRING);
|
||||
if (cp == NULL) {
|
||||
prop_object_release(ps);
|
||||
return (NULL);
|
||||
}
|
||||
strcpy(cp, str);
|
||||
ps->ps_mutable = cp;
|
||||
ps->ps_size = len;
|
||||
}
|
||||
return (ps);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_string_create_cstring_nocopy --
|
||||
* Create an immutable string that contains a refrence to the
|
||||
* provided C string.
|
||||
*/
|
||||
prop_string_t
|
||||
prop_string_create_cstring_nocopy(const char *str)
|
||||
{
|
||||
prop_string_t ps;
|
||||
|
||||
ps = _prop_string_alloc();
|
||||
if (ps != NULL) {
|
||||
ps->ps_immutable = str;
|
||||
ps->ps_size = strlen(str);
|
||||
ps->ps_flags |= PS_F_NOCOPY;
|
||||
}
|
||||
return (ps);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_string_copy --
|
||||
* Copy a string. If the original string is immutable, then the
|
||||
* copy is also immutable and references the same external data.
|
||||
*/
|
||||
prop_string_t
|
||||
prop_string_copy(prop_string_t ops)
|
||||
{
|
||||
prop_string_t ps;
|
||||
|
||||
if (! prop_object_is_string(ops))
|
||||
return (NULL);
|
||||
|
||||
ps = _prop_string_alloc();
|
||||
if (ps != NULL) {
|
||||
ps->ps_size = ops->ps_size;
|
||||
ps->ps_flags = ops->ps_flags;
|
||||
if (ops->ps_flags & PS_F_NOCOPY)
|
||||
ps->ps_immutable = ops->ps_immutable;
|
||||
else {
|
||||
char *cp = _PROP_MALLOC(ps->ps_size + 1, M_PROP_STRING);
|
||||
if (cp == NULL) {
|
||||
prop_object_release(ps);
|
||||
return (NULL);
|
||||
}
|
||||
strcpy(cp, prop_string_contents(ops));
|
||||
ps->ps_mutable = cp;
|
||||
}
|
||||
}
|
||||
return (ps);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_string_copy_mutable --
|
||||
* Copy a string, always returning a mutable copy.
|
||||
*/
|
||||
prop_string_t
|
||||
prop_string_copy_mutable(prop_string_t ops)
|
||||
{
|
||||
prop_string_t ps;
|
||||
char *cp;
|
||||
|
||||
if (! prop_object_is_string(ops))
|
||||
return (NULL);
|
||||
|
||||
ps = _prop_string_alloc();
|
||||
if (ps != NULL) {
|
||||
ps->ps_size = ops->ps_size;
|
||||
cp = _PROP_MALLOC(ps->ps_size + 1, M_PROP_STRING);
|
||||
if (cp == NULL) {
|
||||
prop_object_release(ps);
|
||||
return (NULL);
|
||||
}
|
||||
strcpy(cp, prop_string_contents(ops));
|
||||
ps->ps_mutable = cp;
|
||||
}
|
||||
return (ps);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_string_size --
|
||||
* Return the size of the string, not including the terminating NUL.
|
||||
*/
|
||||
size_t
|
||||
prop_string_size(prop_string_t ps)
|
||||
{
|
||||
|
||||
if (! prop_object_is_string(ps))
|
||||
return (0);
|
||||
|
||||
return (ps->ps_size);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_string_mutable --
|
||||
* Return true if the string is a mutable string.
|
||||
*/
|
||||
bool
|
||||
prop_string_mutable(prop_string_t ps)
|
||||
{
|
||||
|
||||
if (! prop_object_is_string(ps))
|
||||
return (false);
|
||||
|
||||
return ((ps->ps_flags & PS_F_NOCOPY) == 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_string_cstring --
|
||||
* Return a copy of the contents of the string as a C string.
|
||||
* The string is allocated with the M_TEMP malloc type.
|
||||
*/
|
||||
char *
|
||||
prop_string_cstring(prop_string_t ps)
|
||||
{
|
||||
char *cp;
|
||||
|
||||
if (! prop_object_is_string(ps))
|
||||
return (NULL);
|
||||
|
||||
cp = _PROP_MALLOC(ps->ps_size + 1, M_TEMP);
|
||||
if (cp != NULL)
|
||||
strcpy(cp, prop_string_contents(ps));
|
||||
|
||||
return (cp);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_string_cstring_nocopy --
|
||||
* Return an immutable reference to the contents of the string
|
||||
* as a C string.
|
||||
*/
|
||||
const char *
|
||||
prop_string_cstring_nocopy(prop_string_t ps)
|
||||
{
|
||||
|
||||
if (! prop_object_is_string(ps))
|
||||
return (NULL);
|
||||
|
||||
return (prop_string_contents(ps));
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_string_append --
|
||||
* Append the contents of one string to another. Returns true
|
||||
* upon success. The destination string must be mutable.
|
||||
*/
|
||||
bool
|
||||
prop_string_append(prop_string_t dst, prop_string_t src)
|
||||
{
|
||||
char *ocp, *cp;
|
||||
size_t len;
|
||||
|
||||
if (! (prop_object_is_string(dst) &&
|
||||
prop_object_is_string(src)))
|
||||
return (false);
|
||||
|
||||
if (dst->ps_flags & PS_F_NOCOPY)
|
||||
return (false);
|
||||
|
||||
len = dst->ps_size + src->ps_size;
|
||||
cp = _PROP_MALLOC(len + 1, M_PROP_STRING);
|
||||
if (cp == NULL)
|
||||
return (false);
|
||||
snprintf(cp, len + 1, "%s%s", prop_string_contents(dst),
|
||||
prop_string_contents(src));
|
||||
ocp = dst->ps_mutable;
|
||||
dst->ps_mutable = cp;
|
||||
dst->ps_size = len;
|
||||
if (ocp != NULL)
|
||||
_PROP_FREE(ocp, M_PROP_STRING);
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_string_append_cstring --
|
||||
* Append a C string to a string. Returns true upon success.
|
||||
* The destination string must be mutable.
|
||||
*/
|
||||
bool
|
||||
prop_string_append_cstring(prop_string_t dst, const char *src)
|
||||
{
|
||||
char *ocp, *cp;
|
||||
size_t len;
|
||||
|
||||
if (! prop_object_is_string(dst))
|
||||
return (false);
|
||||
|
||||
_PROP_ASSERT(src != NULL);
|
||||
|
||||
if (dst->ps_flags & PS_F_NOCOPY)
|
||||
return (false);
|
||||
|
||||
len = dst->ps_size + strlen(src);
|
||||
cp = _PROP_MALLOC(len + 1, M_PROP_STRING);
|
||||
if (cp == NULL)
|
||||
return (false);
|
||||
snprintf(cp, len + 1, "%s%s", prop_string_contents(dst), src);
|
||||
ocp = dst->ps_mutable;
|
||||
dst->ps_mutable = cp;
|
||||
dst->ps_size = len;
|
||||
if (ocp != NULL)
|
||||
_PROP_FREE(ocp, M_PROP_STRING);
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_string_equals --
|
||||
* Return true if two strings are equivalent.
|
||||
*/
|
||||
bool
|
||||
prop_string_equals(prop_string_t str1, prop_string_t str2)
|
||||
{
|
||||
if (!prop_object_is_string(str1) || !prop_object_is_string(str2))
|
||||
return (false);
|
||||
|
||||
return prop_object_equals(str1, str2);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_string_equals_cstring --
|
||||
* Return true if the string is equivalent to the specified
|
||||
* C string.
|
||||
*/
|
||||
bool
|
||||
prop_string_equals_cstring(prop_string_t ps, const char *cp)
|
||||
{
|
||||
|
||||
if (! prop_object_is_string(ps))
|
||||
return (false);
|
||||
|
||||
return (strcmp(prop_string_contents(ps), cp) == 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* _prop_string_internalize --
|
||||
* Parse a <string>...</string> and return the object created from the
|
||||
* external representation.
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
bool
|
||||
_prop_string_internalize(prop_stack_t stack, prop_object_t *obj,
|
||||
struct _prop_object_internalize_context *ctx)
|
||||
{
|
||||
prop_string_t string;
|
||||
char *str;
|
||||
size_t len, alen;
|
||||
|
||||
if (ctx->poic_is_empty_element) {
|
||||
*obj = prop_string_create();
|
||||
return (true);
|
||||
}
|
||||
|
||||
/* No attributes recognized here. */
|
||||
if (ctx->poic_tagattr != NULL)
|
||||
return (true);
|
||||
|
||||
/* Compute the length of the result. */
|
||||
if (_prop_object_internalize_decode_string(ctx, NULL, 0, &len,
|
||||
NULL) == false)
|
||||
return (true);
|
||||
|
||||
str = _PROP_MALLOC(len + 1, M_PROP_STRING);
|
||||
if (str == NULL)
|
||||
return (true);
|
||||
|
||||
if (_prop_object_internalize_decode_string(ctx, str, len, &alen,
|
||||
&ctx->poic_cp) == false ||
|
||||
alen != len) {
|
||||
_PROP_FREE(str, M_PROP_STRING);
|
||||
return (true);
|
||||
}
|
||||
str[len] = '\0';
|
||||
|
||||
if (_prop_object_internalize_find_tag(ctx, "string",
|
||||
_PROP_TAG_TYPE_END) == false) {
|
||||
_PROP_FREE(str, M_PROP_STRING);
|
||||
return (true);
|
||||
}
|
||||
|
||||
string = _prop_string_alloc();
|
||||
if (string == NULL) {
|
||||
_PROP_FREE(str, M_PROP_STRING);
|
||||
return (true);
|
||||
}
|
||||
|
||||
string->ps_mutable = str;
|
||||
string->ps_size = len;
|
||||
*obj = string;
|
||||
|
||||
return (true);
|
||||
}
|
||||
129
lib/external/portableproplib/prop_zlib.c
vendored
Normal file
129
lib/external/portableproplib/prop_zlib.c
vendored
Normal file
@@ -0,0 +1,129 @@
|
||||
/*-
|
||||
* Copyright (c) 2010-2014 Juan Romero Pardines.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <prop/proplib.h>
|
||||
#include "prop_object_impl.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <zlib.h>
|
||||
|
||||
#define _READ_CHUNK 8192
|
||||
|
||||
#define TEMPLATE(type, objtype) \
|
||||
bool \
|
||||
prop ## type ## _externalize_to_zfile(prop ## type ## _t obj, const char *fname) \
|
||||
{ \
|
||||
char *xml; \
|
||||
bool rv; \
|
||||
int save_errno = 0; \
|
||||
\
|
||||
xml = prop ## type ## _externalize(obj); \
|
||||
if (xml == NULL) \
|
||||
return false; \
|
||||
rv = _prop_object_externalize_write_file(fname, xml, strlen(xml), true); \
|
||||
if (rv == false) \
|
||||
save_errno = errno; \
|
||||
_PROP_FREE(xml, M_TEMP); \
|
||||
if (rv == false) \
|
||||
errno = save_errno; \
|
||||
\
|
||||
return rv; \
|
||||
} \
|
||||
\
|
||||
prop ## type ## _t \
|
||||
prop ## type ## _internalize_from_zfile(const char *fname) \
|
||||
{ \
|
||||
struct _prop_object_internalize_mapped_file *mf; \
|
||||
prop ## type ## _t obj = NULL; \
|
||||
z_stream strm; \
|
||||
unsigned char out[_READ_CHUNK+1]; \
|
||||
char *uncomp_xml = NULL; \
|
||||
size_t have; \
|
||||
ssize_t totalsize = 0; \
|
||||
int rv = 0; \
|
||||
\
|
||||
mf = _prop_object_internalize_map_file(fname); \
|
||||
if (mf == NULL) \
|
||||
return NULL; \
|
||||
\
|
||||
/* If it's an ordinary uncompressed plist we are done */ \
|
||||
obj = prop ## type ## _internalize(mf->poimf_xml); \
|
||||
if (prop_object_type(obj) == PROP_TYPE_## objtype) \
|
||||
goto out; \
|
||||
\
|
||||
/* Output buffer (uncompressed) */ \
|
||||
uncomp_xml = _PROP_MALLOC(_READ_CHUNK, M_TEMP); \
|
||||
if (uncomp_xml == NULL) \
|
||||
goto out; \
|
||||
\
|
||||
/* Decompress the mmap'ed buffer with zlib */ \
|
||||
strm.zalloc = Z_NULL; \
|
||||
strm.zfree = Z_NULL; \
|
||||
strm.opaque = Z_NULL; \
|
||||
strm.avail_in = 0; \
|
||||
strm.next_in = Z_NULL; \
|
||||
\
|
||||
/* 15+16 to use gzip method */ \
|
||||
if (inflateInit2(&strm, 15+16) != Z_OK) \
|
||||
goto out2; \
|
||||
\
|
||||
strm.avail_in = mf->poimf_mapsize; \
|
||||
strm.next_in = (unsigned char *)mf->poimf_xml; \
|
||||
\
|
||||
/* Inflate the input buffer and copy into 'uncomp_xml' */ \
|
||||
do { \
|
||||
strm.avail_out = _READ_CHUNK; \
|
||||
strm.next_out = out; \
|
||||
rv = inflate(&strm, Z_NO_FLUSH); \
|
||||
switch (rv) { \
|
||||
case Z_DATA_ERROR: \
|
||||
case Z_STREAM_ERROR: \
|
||||
case Z_NEED_DICT: \
|
||||
case Z_MEM_ERROR: \
|
||||
errno = EINVAL; \
|
||||
goto out1; \
|
||||
} \
|
||||
have = _READ_CHUNK - strm.avail_out; \
|
||||
totalsize += have; \
|
||||
uncomp_xml = _PROP_REALLOC(uncomp_xml, totalsize, M_TEMP); \
|
||||
memcpy(uncomp_xml + totalsize - have, out, have); \
|
||||
} while (strm.avail_out == 0); \
|
||||
\
|
||||
/* we are done */ \
|
||||
out2: \
|
||||
(void)inflateEnd(&strm); \
|
||||
out1: \
|
||||
obj = prop ## type ## _internalize(uncomp_xml); \
|
||||
_PROP_FREE(uncomp_xml, M_TEMP); \
|
||||
out: \
|
||||
_prop_object_internalize_unmap_file(mf); \
|
||||
\
|
||||
return obj; \
|
||||
}
|
||||
|
||||
TEMPLATE(_array, ARRAY)
|
||||
TEMPLATE(_dictionary, DICTIONARY)
|
||||
|
||||
#undef TEMPLATE
|
||||
1315
lib/external/portableproplib/rb.c
vendored
Normal file
1315
lib/external/portableproplib/rb.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
64
lib/external/strcasestr.c
vendored
Normal file
64
lib/external/strcasestr.c
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
/* $NetBSD: strcasestr.c,v 1.3 2005/11/29 03:12:00 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Chris Torek.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "xbps_api_impl.h"
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* Find the first occurrence of find in s, ignore case.
|
||||
*/
|
||||
char HIDDEN *
|
||||
strcasestr(const char *s, const char *find)
|
||||
{
|
||||
char c, sc;
|
||||
size_t len;
|
||||
|
||||
assert(s != NULL);
|
||||
assert(find != NULL);
|
||||
|
||||
if ((c = *find++) != 0) {
|
||||
c = tolower((unsigned char)c);
|
||||
len = strlen(find);
|
||||
do {
|
||||
do {
|
||||
if ((sc = *s++) == 0)
|
||||
return (NULL);
|
||||
} while ((char)tolower((unsigned char)sc) != c);
|
||||
} while (strncasecmp(s, find, len) != 0);
|
||||
s--;
|
||||
}
|
||||
return __UNCONST(s);
|
||||
}
|
||||
57
lib/external/strlcat.c
vendored
Normal file
57
lib/external/strlcat.c
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
/* $OpenBSD: strlcat.c,v 1.13 2005/08/08 08:05:37 espie Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "compat.h"
|
||||
|
||||
/*
|
||||
* Appends src to string dst of size siz (unlike strncat, siz is the
|
||||
* full size of dst, not space left). At most siz-1 characters
|
||||
* will be copied. Always NUL terminates (unless siz <= strlen(dst)).
|
||||
* Returns strlen(src) + MIN(siz, strlen(initial dst)).
|
||||
* If retval >= siz, truncation occurred.
|
||||
*/
|
||||
size_t HIDDEN
|
||||
strlcat(char *dst, const char *src, size_t siz)
|
||||
{
|
||||
char *d = dst;
|
||||
const char *s = src;
|
||||
size_t n = siz;
|
||||
size_t dlen;
|
||||
|
||||
/* Find the end of dst and adjust bytes left but don't go past end */
|
||||
while (n-- != 0 && *d != '\0')
|
||||
d++;
|
||||
dlen = d - dst;
|
||||
n = siz - dlen;
|
||||
|
||||
if (n == 0)
|
||||
return(dlen + strlen(s));
|
||||
while (*s != '\0') {
|
||||
if (n != 1) {
|
||||
*d++ = *s;
|
||||
n--;
|
||||
}
|
||||
s++;
|
||||
}
|
||||
*d = '\0';
|
||||
|
||||
return(dlen + (s - src)); /* count does not include NUL */
|
||||
}
|
||||
53
lib/external/strlcpy.c
vendored
Normal file
53
lib/external/strlcpy.c
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
/* $OpenBSD: strlcpy.c,v 1.11 2006/05/05 15:27:38 millert Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "compat.h"
|
||||
|
||||
/*
|
||||
* Copy src to string dst of size siz. At most siz-1 characters
|
||||
* will be copied. Always NUL terminates (unless siz == 0).
|
||||
* Returns strlen(src); if retval >= siz, truncation occurred.
|
||||
*/
|
||||
size_t HIDDEN
|
||||
strlcpy(char *dst, const char *src, size_t siz)
|
||||
{
|
||||
char *d = dst;
|
||||
const char *s = src;
|
||||
size_t n = siz;
|
||||
|
||||
/* Copy as many bytes as will fit */
|
||||
if (n != 0) {
|
||||
while (--n != 0) {
|
||||
if ((*d++ = *s++) == '\0')
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Not enough room in dst, add NUL and traverse rest of src */
|
||||
if (n == 0) {
|
||||
if (siz != 0)
|
||||
*d = '\0'; /* NUL-terminate dst */
|
||||
while (*s++)
|
||||
;
|
||||
}
|
||||
|
||||
return(s - src - 1); /* count does not include NUL */
|
||||
}
|
||||
82
lib/external/vasprintf.c
vendored
Normal file
82
lib/external/vasprintf.c
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
/* $NetBSD: asprintf.c,v 1.2 2007/07/20 00:10:06 tnn Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2007 Joerg Sonnenberger <joerg@NetBSD.org>.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include "compat.h"
|
||||
|
||||
int HIDDEN
|
||||
vasprintf(char **ret, const char *fmt, va_list ap)
|
||||
{
|
||||
char *buf, *new_buf;
|
||||
size_t len;
|
||||
int retval;
|
||||
|
||||
len = 128;
|
||||
buf = malloc(len);
|
||||
if (buf == NULL) {
|
||||
*ret = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
retval = vsnprintf(buf, len, fmt, ap);
|
||||
if (retval < 0) {
|
||||
free(buf);
|
||||
*ret = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (retval < (int)len) {
|
||||
new_buf = realloc(buf, retval + 1);
|
||||
if (new_buf == NULL)
|
||||
*ret = buf;
|
||||
else
|
||||
*ret = new_buf;
|
||||
return retval;
|
||||
}
|
||||
|
||||
len = (size_t)retval + 1;
|
||||
free(buf);
|
||||
buf = malloc(len);
|
||||
if (buf == NULL) {
|
||||
*ret = NULL;
|
||||
return -1;
|
||||
}
|
||||
retval = vsnprintf(buf, len, fmt, ap);
|
||||
if (retval != (int)len - 1) {
|
||||
free(buf);
|
||||
*ret = NULL;
|
||||
return -1;
|
||||
}
|
||||
*ret = buf;
|
||||
return retval;
|
||||
}
|
||||
Reference in New Issue
Block a user