#include "pblock.h"
#include "plist_pvt.h"
#include "plist.h"
#include "util.h"
#include "pool.h"
#include "systhr.h"
#define MALLOC_POOL_HANDLE (thread_malloc_key != -
1 ? (
pool_handle_t *)systhread_getdata(thread_malloc_key) : getThreadMallocPool())
static int thread_malloc_key = -
1;
static int _pblock_str2pblock(
const char* str, pblock* pb, PRBool lowerCase);
static pool_handle_t *getThreadMallocPool()
{
pool_handle_t *thread_malloc_pool =
0;
thread_malloc_key = getThreadMallocKey();
if (thread_malloc_key != -
1) {
thread_malloc_pool = (
pool_handle_t *)systhread_getdata(thread_malloc_key);
}
return thread_malloc_pool;
}
typedef struct pb_key pb_key;
struct pb_key {
const char *name;
int namelen;
unsigned int hashval;
int sizendx;
int hashndx;
};
#define PB_KEY_LIST_BUCKET_COUNT 0x7f
struct pb_key_list_bucket {
pb_key **elements;
unsigned size;
};
struct pb_key_list {
struct pb_key_list_bucket buckets[
PB_KEY_LIST_BUCKET_COUNT +
1];
};
static void _pb_key_list_insert(
struct pb_key_list *hashList,
unsigned int hashval, pb_key* element) {
struct pb_key_list_bucket *bucket = &hashList->buckets[hashval &
PB_KEY_LIST_BUCKET_COUNT];
size_t idx = bucket->size;
bucket->size++;
bucket->elements = realloc(bucket->elements,
sizeof(pb_key*) * bucket->size);
if (bucket->elements ==
NULL) abort();
bucket->elements[idx] = element;
}
static struct pb_key_list _pbKeys;
static const pb_key *_create_key(
const char *name)
{
pb_key *key = malloc(
sizeof(pb_key));
if (key ==
NULL) abort();
key->name =
STRDUP(name);
key->namelen = strlen(name);
key->hashval = PListHash(name);
key->sizendx =
0;
key->hashndx = key->hashval %
PLSIZENDX(
0);
_pb_key_list_insert(&_pbKeys, key->hashval, key);
return key;
}
const pb_key *pb_key_accept;
const pb_key *pb_key_accept_charset;
const pb_key *pb_key_accept_encoding;
const pb_key *pb_key_accept_language;
const pb_key *pb_key_accept_ranges;
const pb_key *pb_key_actual_route;
const pb_key *pb_key_age;
const pb_key *pb_key_always_allow_chunked;
const pb_key *pb_key_always_use_keep_alive;
const pb_key *pb_key_auth_cert;
const pb_key *pb_key_auth_expiring;
const pb_key *pb_key_auth_group;
const pb_key *pb_key_auth_type;
const pb_key *pb_key_auth_user;
const pb_key *pb_key_authorization;
const pb_key *pb_key_browser;
const pb_key *pb_key_c2p_cl;
const pb_key *pb_key_c2p_hl;
const pb_key *pb_key_cache_info;
const pb_key *pb_key_charset;
const pb_key *pb_key_check_http_server;
const pb_key *pb_key_ChunkedRequestBufferSize;
const pb_key *pb_key_ChunkedRequestTimeout;
const pb_key *pb_key_cipher;
const pb_key *pb_key_clf_request;
const pb_key *pb_key_cli_status;
const pb_key *pb_key_client_cert_nickname;
const pb_key *pb_key_client_ip;
const pb_key *pb_key_close;
const pb_key *pb_key_connect_timeout;
const pb_key *pb_key_connection;
const pb_key *pb_key_cont;
const pb_key *pb_key_content_encoding;
const pb_key *pb_key_content_language;
const pb_key *pb_key_content_length;
const pb_key *pb_key_content_location;
const pb_key *pb_key_content_md5;
const pb_key *pb_key_content_range;
const pb_key *pb_key_content_type;
const pb_key *pb_key_cookie;
const pb_key *pb_key_date;
const pb_key *pb_key_DATE_GMT;
const pb_key *pb_key_DATE_LOCAL;
const pb_key *pb_key_dir;
const pb_key *pb_key_Directive;
const pb_key *pb_key_dns;
const pb_key *pb_key_DOCUMENT_NAME;
const pb_key *pb_key_DOCUMENT_URI;
const pb_key *pb_key_domain;
const pb_key *pb_key_enc;
const pb_key *pb_key_engine;
const pb_key *pb_key_error_action;
const pb_key *pb_key_error_desc;
const pb_key *pb_key_error_fn;
const pb_key *pb_key_escape;
const pb_key *pb_key_escaped;
const pb_key *pb_key_etag;
const pb_key *pb_key_expect;
const pb_key *pb_key_expires;
const pb_key *pb_key_expr;
const pb_key *pb_key_filter;
const pb_key *pb_key_find_pathinfo_forward;
const pb_key *pb_key_flushTimer;
const pb_key *pb_key_fn;
const pb_key *pb_key_from;
const pb_key *pb_key_full_headers;
const pb_key *pb_key_hdr;
const pb_key *pb_key_host;
const pb_key *pb_key_hostname;
const pb_key *pb_key_if_match;
const pb_key *pb_key_if_modified_since;
const pb_key *pb_key_if_none_match;
const pb_key *pb_key_if_range;
const pb_key *pb_key_if_unmodified_since;
const pb_key *pb_key_ip;
const pb_key *pb_key_iponly;
const pb_key *pb_key_issuer_dn;
const pb_key *pb_key_jroute;
const pb_key *pb_key_keep_alive;
const pb_key *pb_key_keep_alive_timeout;
const pb_key *pb_key_keysize;
const pb_key *pb_key_lang;
const pb_key *pb_key_last_modified;
const pb_key *pb_key_level;
const pb_key *pb_key_location;
const pb_key *pb_key_lock_owner;
const pb_key *pb_key_magnus_charset;
const pb_key *pb_key_magnus_internal;
const pb_key *pb_key_magnus_internal_dav_src;
const pb_key *pb_key_magnus_internal_default_acls_only;
const pb_key *pb_key_magnus_internal_error_j2ee;
const pb_key *pb_key_magnus_internal_j2ee_nsapi;
const pb_key *pb_key_magnus_internal_preserve_srvhdrs;
const pb_key *pb_key_magnus_internal_set_request_status;
const pb_key *pb_key_magnus_internal_set_response_status;
const pb_key *pb_key_magnus_internal_webapp_errordesc;
const pb_key *pb_key_matched_browser;
const pb_key *pb_key_max_age;
const pb_key *pb_key_max_forwards;
const pb_key *pb_key_message;
const pb_key *pb_key_method;
const pb_key *pb_key_name;
const pb_key *pb_key_nocache;
const pb_key *pb_key_nostat;
const pb_key *pb_key_ntrans_base;
const pb_key *pb_key_offline_origin_addr;
const pb_key *pb_key_offline_proxy_addr;
const pb_key *pb_key_origin_addr;
const pb_key *pb_key_p2c_cl;
const pb_key *pb_key_p2c_hl;
const pb_key *pb_key_p2r_cl;
const pb_key *pb_key_p2r_hl;
const pb_key *pb_key_parse_timeout;
const pb_key *pb_key_password;
const pb_key *pb_key_path;
const pb_key *pb_key_PATH_INFO;
const pb_key *pb_key_path_info;
const pb_key *pb_key_pblock;
const pb_key *pb_key_poll_interval;
const pb_key *pb_key_pool;
const pb_key *pb_key_port;
const pb_key *pb_key_ppath;
const pb_key *pb_key_pragma;
const pb_key *pb_key_process_request_body;
const pb_key *pb_key_process_response_body;
const pb_key *pb_key_protocol;
const pb_key *pb_key_proxy_addr;
const pb_key *pb_key_proxy_agent;
const pb_key *pb_key_proxy_auth_cert;
const pb_key *pb_key_proxy_authorization;
const pb_key *pb_key_proxy_cipher;
const pb_key *pb_key_proxy_issuer_dn;
const pb_key *pb_key_proxy_jroute;
const pb_key *pb_key_proxy_keysize;
const pb_key *pb_key_proxy_ping;
const pb_key *pb_key_proxy_request;
const pb_key *pb_key_proxy_secret_keysize;
const pb_key *pb_key_proxy_ssl_id;
const pb_key *pb_key_proxy_user_dn;
const pb_key *pb_key_query;
const pb_key *pb_key_QUERY_STRING;
const pb_key *pb_key_QUERY_STRING_UNESCAPED;
const pb_key *pb_key_r2p_cl;
const pb_key *pb_key_r2p_hl;
const pb_key *pb_key_range;
const pb_key *pb_key_referer;
const pb_key *pb_key_reformat_request_headers;
const pb_key *pb_key_remote_status;
const pb_key *pb_key_request_jroute;
const pb_key *pb_key_required_rights;
const pb_key *pb_key_retries;
const pb_key *pb_key_rewrite_content_location;
const pb_key *pb_key_rewrite_host;
const pb_key *pb_key_rewrite_location;
const pb_key *pb_key_rewrite_set_cookie;
const pb_key *pb_key_root;
const pb_key *pb_key_route;
const pb_key *pb_key_route_cookie;
const pb_key *pb_key_route_hdr;
const pb_key *pb_key_route_offline;
const pb_key *pb_key_script_name;
const pb_key *pb_key_secret_keysize;
const pb_key *pb_key_secure;
const pb_key *pb_key_server;
const pb_key *pb_key_set_cookie;
const pb_key *pb_key_socks_addr;
const pb_key *pb_key_ssl_id;
const pb_key *pb_key_ssl_unclean_shutdown;
const pb_key *pb_key_status;
const pb_key *pb_key_sticky_cookie;
const pb_key *pb_key_sticky_param;
const pb_key *pb_key_suppress_request_headers;
const pb_key *pb_key_svr_status;
const pb_key *pb_key_timeout;
const pb_key *pb_key_to;
const pb_key *pb_key_transfer_encoding;
const pb_key *pb_key_transmit_timeout;
const pb_key *pb_key_tunnel_non_http_response;
const pb_key *pb_key_type;
const pb_key *pb_key_upstream_jroute;
const pb_key *pb_key_uri;
const pb_key *pb_key_url;
const pb_key *pb_key_url_prefix;
const pb_key *pb_key_UseOutputStreamSize;
const pb_key *pb_key_user;
const pb_key *pb_key_user_agent;
const pb_key *pb_key_user_dn;
const pb_key *pb_key_validate_server_cert;
const pb_key *pb_key_value;
const pb_key *pb_key_vary;
const pb_key *pb_key_via;
const pb_key *pb_key_warning;
const pb_key *pb_key_depth;
const pb_key *pb_key_if;
const pb_key *pb_key_vfs;
const pb_key *pb_key_dav;
const pb_key *pb_key_vfsclass;
const pb_key *pb_key_davclass;
NSAPI_PUBLIC void pblock_init_default_keys(
void) {
pb_key_accept = _create_key(
"accept");
pb_key_accept_charset = _create_key(
"accept-charset");
pb_key_accept_encoding = _create_key(
"accept-encoding");
pb_key_accept_language = _create_key(
"accept-language");
pb_key_accept_ranges = _create_key(
"accept-ranges");
pb_key_actual_route = _create_key(
"actual-route");
pb_key_age = _create_key(
"age");
pb_key_always_allow_chunked = _create_key(
"always-allow-chunked");
pb_key_always_use_keep_alive = _create_key(
"always-use-keep-alive");
pb_key_auth_cert = _create_key(
"auth-cert");
pb_key_auth_expiring = _create_key(
"auth-expiring");
pb_key_auth_group = _create_key(
"auth-group");
pb_key_auth_type = _create_key(
"auth-type");
pb_key_auth_user = _create_key(
"auth-user");
pb_key_authorization = _create_key(
"authorization");
pb_key_browser = _create_key(
"browser");
pb_key_c2p_cl = _create_key(
"c2p-cl");
pb_key_c2p_hl = _create_key(
"c2p-hl");
pb_key_cache_info = _create_key(
"cache-info");
pb_key_charset = _create_key(
"charset");
pb_key_check_http_server = _create_key(
"check-http-server");
pb_key_ChunkedRequestBufferSize = _create_key(
"ChunkedRequestBufferSize");
pb_key_ChunkedRequestTimeout = _create_key(
"ChunkedRequestTimeout");
pb_key_cipher = _create_key(
"cipher");
pb_key_clf_request = _create_key(
"clf-request");
pb_key_cli_status = _create_key(
"cli-status");
pb_key_client_cert_nickname = _create_key(
"client-cert-nickname");
pb_key_client_ip = _create_key(
"client-ip");
pb_key_close = _create_key(
"close");
pb_key_connect_timeout = _create_key(
"connect-timeout");
pb_key_connection = _create_key(
"connection");
pb_key_cont = _create_key(
"cont");
pb_key_content_encoding = _create_key(
"content-encoding");
pb_key_content_language = _create_key(
"content-language");
pb_key_content_length = _create_key(
"content-length");
pb_key_content_location = _create_key(
"content-location");
pb_key_content_md5 = _create_key(
"content-md5");
pb_key_content_range = _create_key(
"content-range");
pb_key_content_type = _create_key(
"content-type");
pb_key_cookie = _create_key(
"cookie");
pb_key_date = _create_key(
"date");
pb_key_DATE_GMT = _create_key(
"DATE_GMT");
pb_key_DATE_LOCAL = _create_key(
"DATE_LOCAL");
pb_key_dir = _create_key(
"dir");
pb_key_Directive = _create_key(
"Directive");
pb_key_dns = _create_key(
"dns");
pb_key_DOCUMENT_NAME = _create_key(
"DOCUMENT_NAME");
pb_key_DOCUMENT_URI = _create_key(
"DOCUMENT_URI");
pb_key_domain = _create_key(
"domain");
pb_key_enc = _create_key(
"enc");
pb_key_engine = _create_key(
"engine");
pb_key_error_action = _create_key(
"error-action");
pb_key_error_desc = _create_key(
"error-desc");
pb_key_error_fn = _create_key(
"error-fn");
pb_key_escape = _create_key(
"escape");
pb_key_escaped = _create_key(
"escaped");
pb_key_etag = _create_key(
"etag");
pb_key_expect = _create_key(
"expect");
pb_key_expires = _create_key(
"expires");
pb_key_expr = _create_key(
"expr");
pb_key_filter = _create_key(
"filter");
pb_key_find_pathinfo_forward = _create_key(
"find-pathinfo-forward");
pb_key_flushTimer = _create_key(
"flushTimer");
pb_key_fn = _create_key(
"fn");
pb_key_from = _create_key(
"from");
pb_key_full_headers = _create_key(
"full-headers");
pb_key_hdr = _create_key(
"hdr");
pb_key_host = _create_key(
"host");
pb_key_hostname = _create_key(
"hostname");
pb_key_if_match = _create_key(
"if-match");
pb_key_if_modified_since = _create_key(
"if-modified-since");
pb_key_if_none_match = _create_key(
"if-none-match");
pb_key_if_range = _create_key(
"if-range");
pb_key_if_unmodified_since = _create_key(
"if-unmodified-since");
pb_key_ip = _create_key(
"ip");
pb_key_iponly = _create_key(
"iponly");
pb_key_issuer_dn = _create_key(
"issuer_dn");
pb_key_jroute = _create_key(
"jroute");
pb_key_keep_alive = _create_key(
"keep-alive");
pb_key_keep_alive_timeout = _create_key(
"keep-alive-timeout");
pb_key_keysize = _create_key(
"keysize");
pb_key_lang = _create_key(
"lang");
pb_key_last_modified = _create_key(
"last-modified");
pb_key_level = _create_key(
"level");
pb_key_location = _create_key(
"location");
pb_key_lock_owner = _create_key(
"lock-owner");
pb_key_magnus_charset = _create_key(
"magnus-charset");
pb_key_magnus_internal = _create_key(
"magnus-internal");
pb_key_magnus_internal_dav_src = _create_key(
"magnus-internal/dav-src");
pb_key_magnus_internal_default_acls_only = _create_key(
"magnus-internal/default-acls-only");
pb_key_magnus_internal_error_j2ee = _create_key(
"magnus-internal/error-j2ee");
pb_key_magnus_internal_j2ee_nsapi = _create_key(
"magnus-internal/j2ee-nsapi");
pb_key_magnus_internal_preserve_srvhdrs = _create_key(
"magnus-internal/preserve-srvhdrs-after-req-restart");
pb_key_magnus_internal_set_request_status = _create_key(
"magnus-internal/set-request-status");
pb_key_magnus_internal_set_response_status = _create_key(
"magnus-internal/set-response-status");
pb_key_magnus_internal_webapp_errordesc = _create_key(
"magnus-internal/webapp-errordesc");
pb_key_matched_browser = _create_key(
"matched-browser");
pb_key_max_age = _create_key(
"max-age");
pb_key_max_forwards = _create_key(
"max-forwards");
pb_key_message = _create_key(
"message");
pb_key_method = _create_key(
"method");
pb_key_name = _create_key(
"name");
pb_key_nocache = _create_key(
"nocache");
pb_key_nostat = _create_key(
"nostat");
pb_key_ntrans_base = _create_key(
"ntrans-base");
pb_key_offline_origin_addr = _create_key(
"offline-origin-addr");
pb_key_offline_proxy_addr = _create_key(
"offline-proxy-addr");
pb_key_origin_addr = _create_key(
"origin-addr");
pb_key_p2c_cl = _create_key(
"p2c-cl");
pb_key_p2c_hl = _create_key(
"p2c-hl");
pb_key_p2r_cl = _create_key(
"p2r-cl");
pb_key_p2r_hl = _create_key(
"p2r-hl");
pb_key_parse_timeout = _create_key(
"parse-timeout");
pb_key_password = _create_key(
"password");
pb_key_path = _create_key(
"path");
pb_key_PATH_INFO = _create_key(
"PATH_INFO");
pb_key_path_info = _create_key(
"path-info");
pb_key_pblock = _create_key(
"pblock");
pb_key_poll_interval = _create_key(
"poll-interval");
pb_key_pool = _create_key(
"pool");
pb_key_port = _create_key(
"port");
pb_key_ppath = _create_key(
"ppath");
pb_key_pragma = _create_key(
"pragma");
pb_key_process_request_body = _create_key(
"process-request-body");
pb_key_process_response_body = _create_key(
"process-response-body");
pb_key_protocol = _create_key(
"protocol");
pb_key_proxy_addr = _create_key(
"proxy-addr");
pb_key_proxy_agent = _create_key(
"proxy-agent");
pb_key_proxy_auth_cert = _create_key(
"proxy-auth-cert");
pb_key_proxy_authorization = _create_key(
"proxy-authorization");
pb_key_proxy_cipher = _create_key(
"proxy-cipher");
pb_key_proxy_issuer_dn = _create_key(
"proxy-issuer-dn");
pb_key_proxy_jroute = _create_key(
"proxy-jroute");
pb_key_proxy_keysize = _create_key(
"proxy-keysize");
pb_key_proxy_ping = _create_key(
"proxy-ping");
pb_key_proxy_request = _create_key(
"proxy-request");
pb_key_proxy_secret_keysize = _create_key(
"proxy-secret-keysize");
pb_key_proxy_ssl_id = _create_key(
"proxy-ssl-id");
pb_key_proxy_user_dn = _create_key(
"proxy-user-dn");
pb_key_query = _create_key(
"query");
pb_key_QUERY_STRING = _create_key(
"QUERY_STRING");
pb_key_QUERY_STRING_UNESCAPED = _create_key(
"QUERY_STRING_UNESCAPED");
pb_key_r2p_cl = _create_key(
"r2p-cl");
pb_key_r2p_hl = _create_key(
"r2p-hl");
pb_key_range = _create_key(
"range");
pb_key_referer = _create_key(
"referer");
pb_key_reformat_request_headers = _create_key(
"reformat-request-headers");
pb_key_remote_status = _create_key(
"remote-status");
pb_key_request_jroute = _create_key(
"request-jroute");
pb_key_required_rights = _create_key(
"required-rights");
pb_key_retries = _create_key(
"retries");
pb_key_rewrite_content_location = _create_key(
"rewrite-content-location");
pb_key_rewrite_host = _create_key(
"rewrite-host");
pb_key_rewrite_location = _create_key(
"rewrite-location");
pb_key_rewrite_set_cookie = _create_key(
"rewrite-set-cookie");
pb_key_root = _create_key(
"root");
pb_key_route = _create_key(
"route");
pb_key_route_cookie = _create_key(
"route-cookie");
pb_key_route_hdr = _create_key(
"route-hdr");
pb_key_route_offline = _create_key(
"route-offline");
pb_key_script_name = _create_key(
"script-name");
pb_key_secret_keysize = _create_key(
"secret-keysize");
pb_key_secure = _create_key(
"secure");
pb_key_server = _create_key(
"server");
pb_key_set_cookie = _create_key(
"set-cookie");
pb_key_socks_addr = _create_key(
"socks_addr");
pb_key_ssl_id = _create_key(
"ssl-id");
pb_key_ssl_unclean_shutdown = _create_key(
"ssl-unclean-shutdown");
pb_key_status = _create_key(
"status");
pb_key_sticky_cookie = _create_key(
"sticky-cookie");
pb_key_sticky_param = _create_key(
"sticky-param");
pb_key_suppress_request_headers = _create_key(
"suppress-request-headers");
pb_key_svr_status = _create_key(
"svr-status");
pb_key_timeout = _create_key(
"timeout");
pb_key_to = _create_key(
"to");
pb_key_transfer_encoding = _create_key(
"transfer-encoding");
pb_key_transmit_timeout = _create_key(
"transmit-timeout");
pb_key_tunnel_non_http_response = _create_key(
"tunnel-non-http-response");
pb_key_type = _create_key(
"type");
pb_key_upstream_jroute = _create_key(
"upstream-jroute");
pb_key_uri = _create_key(
"uri");
pb_key_url = _create_key(
"url");
pb_key_url_prefix = _create_key(
"url-prefix");
pb_key_UseOutputStreamSize = _create_key(
"UseOutputStreamSize");
pb_key_user = _create_key(
"user");
pb_key_user_agent = _create_key(
"user-agent");
pb_key_user_dn = _create_key(
"user_dn");
pb_key_validate_server_cert = _create_key(
"validate-server-cert");
pb_key_value = _create_key(
"value");
pb_key_vary = _create_key(
"vary");
pb_key_via = _create_key(
"via");
pb_key_warning = _create_key(
"warning");
pb_key_depth = _create_key(
"depth");
pb_key_if = _create_key(
"if");
pb_key_vfs = _create_key(
"vfs");
pb_key_dav = _create_key(
"dav");
pb_key_vfsclass = _create_key(
"vfsclass");
pb_key_davclass = _create_key(
"davclass");
}
NSAPI_PUBLIC void pblock_free_default_keys(
void) {
for (
unsigned i =
0 ; i <
PB_KEY_LIST_BUCKET_COUNT ; i++) {
unsigned count = _pbKeys.buckets[i].size;
if (count >
0) {
pb_key **keys = _pbKeys.buckets[i].elements;
for (
unsigned j =
0 ; j < count ; j++) {
pb_key *key = keys[j];
if(key) {
free((
char*)key->name);
free(key);
}
}
free(keys);
}
}
}
static inline
const pb_key *_find_key(
const char *name,
unsigned int hashval)
{
struct pb_key_list_bucket *bucket = &_pbKeys.buckets[hashval &
PB_KEY_LIST_BUCKET_COUNT];
for (
unsigned i =
0 ; i < bucket->size ; i++) {
pb_key *key = bucket->elements[i];
if (key->hashval == hashval && !strcmp(key->name, name)) {
return key;
}
}
return NULL;
}
static inline
int _get_hash_index(
const PListStruct_t *pl,
const pb_key *key)
{
int i;
if (key->sizendx == pl->pl_symtab->pt_sizendx)
i = key->hashndx;
else
i = key->hashval %
PLSIZENDX(pl->pl_symtab->pt_sizendx);
return i;
}
static inline pb_param *_param_create(
pool_handle_t *pool_handle,
const char *name,
int namelen,
const char *value,
int valuelen)
{
PLValueStruct_t *ret;
ret = (
PLValueStruct_t *)pool_malloc(pool_handle,
sizeof(
PLValueStruct_t));
ret->pv_pbentry.param = &ret->pv_pbparam;
ret->pv_pbentry.next =
0;
ret->pv_next =
0;
ret->pv_type =
0;
ret->pv_mempool = pool_handle;
if (name || namelen) {
ret->pv_name = (
char*)pool_malloc(pool_handle, namelen +
1);
if (name) {
memcpy(ret->pv_name, name, namelen);
ret->pv_name[namelen] =
'\0';
}
else {
ret->pv_name[
0] =
'\0';
}
}
else {
ret->pv_name =
0;
}
if (value || valuelen) {
ret->pv_value = (
char*)pool_malloc(pool_handle, valuelen +
1);
if (value) {
memcpy(ret->pv_value, value, valuelen);
ret->pv_value[valuelen] =
'\0';
}
else {
ret->pv_value[
0] =
'\0';
}
}
else {
ret->pv_value =
0;
}
return &ret->pv_pbparam;
}
NSAPI_PUBLIC pb_param *pblock_key_param_create(pblock *pb,
const pb_key *key,
const char *value,
int valuelen)
{
PListStruct_t *pl =
PBTOPL(pb);
return _param_create(pl->pl_mempool, key->name, key->namelen, value, valuelen);
}
NSAPI_PUBLIC pb_param *pblock_param_create(pblock *pb,
const char *name,
const char *value)
{
PListStruct_t *pl =
PBTOPL(pb);
return _param_create(pl->pl_mempool, name, name ? strlen(name) :
0, value, value ? strlen(value) :
0);
}
NSAPI_PUBLIC pb_param *param_create(
const char *name,
const char *value)
{
return _param_create(system_pool(), name, name ? strlen(name) :
0, value, value ? strlen(value) :
0);
}
NSAPI_PUBLIC int param_free(pb_param *pp)
{
if (pp) {
PLValueStruct_t *pv =
PATOPV(pp);
if (!pv->pv_mempool) {
pool_free(pv->pv_mempool, pv->pv_name);
pool_free(pv->pv_mempool, pv->pv_value);
pool_free(pv->pv_mempool, pv);
}
return 1;
}
return 0;
}
NSAPI_PUBLIC pblock *pblock_create_pool(
pool_handle_t *pool_handle,
int n)
{
PListStruct_t *plist = (
PListStruct_t *)PListCreate(pool_handle, n,
0,
0);
if (!plist)
return NULL;
plist->pl_resvpi =
0;
return &plist->pl_pb;
}
NSAPI_PUBLIC pool_handle_t *pblock_pool(pblock *pb)
{
PListStruct_t *pl =
PBTOPL(pb);
return pl->pl_mempool;
}
NSAPI_PUBLIC pblock *pblock_create(
int n)
{
return pblock_create_pool(
MALLOC_POOL_HANDLE, n);
}
NSAPI_PUBLIC void pblock_free(pblock *pb)
{
PListStruct_t *pl =
PBTOPL(pb);
PLValueStruct_t **ppval;
PLValueStruct_t *pv;
int i;
if (!pb) {
return;
}
if (pl->pl_mempool || pool_enabled()) {
return;
}
if (pl->pl_symtab) {
pool_free(pl->pl_mempool, (
void *)(pl->pl_symtab));
}
ppval = (
PLValueStruct_t **)(pl->pl_ppval);
for (i =
0; i < pl->pl_initpi; ++i) {
pv = ppval[i];
if (pv) {
param_free(&pv->pv_pbparam);
}
}
pool_free(pl->pl_mempool, (
void *)ppval);
pool_free(pl->pl_mempool, (
void *)pl);
}
NSAPI_PUBLIC const pb_key *pblock_key(
const char *name)
{
if (!name)
return NULL;
return _find_key(name, PListHash(name));
}
NSAPI_PUBLIC void pblock_kpinsert(
const pb_key *key, pb_param *pp, pblock *pb)
{
PListStruct_t *pl =
PBTOPL(pb);
PLValueStruct_t *pv =
PATOPV(pp);
unsigned int hashval;
if (!key) {
hashval = PListHash(pv->pv_name);
key = _find_key(pv->pv_name, hashval);
}
int pindex = PListGetFreeIndex(pl);
if (pindex <
1) {
printf(
"Error - invalid property index\n");
return;
}
PLSymbolTable_t *pt = PListSymbolTable(pl);
if (!pt) {
printf(
"!pt\n");
return;
}
PLValueStruct_t **ppval = (
PLValueStruct_t **)(pl->pl_ppval);
pv->pv_pbkey = key;
pv->pv_pi = pindex;
ppval[pv->pv_pi -
1] = pv;
int i = key ? _get_hash_index(pl, key) : (hashval %
PLSIZENDX(pt->pt_sizendx));
pv->pv_next = pt->pt_hash[i];
pt->pt_hash[i] = pv;
pt->pt_nsyms++;
}
NSAPI_PUBLIC void pblock_pinsert(pb_param *pp, pblock *pb)
{
pblock_kpinsert(
NULL, pp, pb);
}
NSAPI_PUBLIC pb_param *pblock_nvinsert(
const char *name,
const char *value, pblock *pb)
{
pb_param *pp = pblock_param_create(pb, name, value);
if (pp)
pblock_kpinsert(
NULL, pp, pb);
return pp;
}
NSAPI_PUBLIC pb_param *pblock_kvinsert(
const pb_key *key,
const char *value,
int valuelen, pblock *pb)
{
pb_param *pp = pblock_key_param_create(pb, key, value, valuelen);
if (pp)
pblock_kpinsert(key, pp, pb);
return pp;
}
NSAPI_PUBLIC pb_param *pblock_nninsert(
const char *name,
int value, pblock *pb)
{
char num[
UTIL_ITOA_SIZE];
util_itoa(value, num);
return pblock_nvinsert(name, num, pb);
}
NSAPI_PUBLIC pb_param *pblock_kninsert(
const pb_key *key,
int value, pblock *pb)
{
pb_param *pp = pblock_key_param_create(pb, key,
NULL,
UTIL_ITOA_SIZE);
if (pp) {
util_itoa(value, pp->value);
pblock_kpinsert(key, pp, pb);
}
return pp;
}
NSAPI_PUBLIC pb_param *pblock_kllinsert(
const pb_key *key,
int64_t value, pblock *pb)
{
pb_param *pp = pblock_key_param_create(pb, key,
NULL,
UTIL_I64TOA_SIZE);
if (pp) {
util_i64toa(value, pp->value);
pblock_kpinsert(key, pp, pb);
}
return pp;
}
NSAPI_PUBLIC pb_param *pblock_nvlinsert(
const char *name,
int namelen,
const char *value,
int valuelen, pblock *pb)
{
PListStruct_t *pl =
PBTOPL(pb);
pb_param *pp = _param_create(pl->pl_mempool, name, namelen, value, valuelen);
if(pp) {
pblock_kpinsert(
NULL, pp, pb);
}
return pp;
}
NSAPI_PUBLIC pb_param *pblock_findkey(
const pb_key *key,
const pblock *pb)
{
PListStruct_t *pl =
PBTOPL(pb);
if (pl->pl_symtab) {
int i = _get_hash_index(pl, key);
PLValueStruct_t *pv;
for (pv = pl->pl_symtab->pt_hash[i]; pv; pv = pv->pv_next) {
if (pv->pv_pbkey == key)
return &pv->pv_pbparam;
}
}
return NULL;
}
NSAPI_PUBLIC char *pblock_findkeyval(
const pb_key *key,
const pblock *pb)
{
pb_param *pp = pblock_findkey(key, pb);
return pp ? pp->value :
NULL;
}
NSAPI_PUBLIC char *pblock_findval(
const char *name,
const pblock *pb)
{
void *pvalue =
0;
(
void)PListFindValue((
PList_t)(
PBTOPL(pb)), name, &pvalue,
0);
return (
char *)pvalue;
}
NSAPI_PUBLIC pb_param *pblock_fr(
const char *name, pblock *pb,
int remove)
{
PListStruct_t *pl =
PBTOPL(pb);
PLValueStruct_t **ppval;
PLValueStruct_t **pvp;
PLValueStruct_t *pv =
NULL;
int pindex;
int i;
if (pl->pl_symtab) {
i = PListHashName(pl->pl_symtab, name);
for (pvp = &pl->pl_symtab->pt_hash[i];
(pv = *pvp); pvp = &(*pvp)->pv_next) {
if (!strcmp(name, pv->pv_name)) {
if (remove) {
*pvp = pv->pv_next;
pl->pl_symtab->pt_nsyms--;
ppval = (
PLValueStruct_t **)(pl->pl_ppval);
pindex = pv->pv_pi;
ppval[pindex -
1] =
0;
}
break;
}
}
}
return (pv) ? &pv->pv_pbparam :
NULL;
}
NSAPI_PUBLIC pb_param *pblock_removekey(
const pb_key *key, pblock *pb)
{
PListStruct_t *pl =
PBTOPL(pb);
PLValueStruct_t **ppval;
PLValueStruct_t **pvp;
PLValueStruct_t *pv =
NULL;
int pindex;
int i;
if (pl->pl_symtab) {
i = _get_hash_index(pl, key);
for (pvp = &pl->pl_symtab->pt_hash[i]; (pv = *pvp); pvp = &pv->pv_next) {
if (pv->pv_pbkey == key) {
*pvp = pv->pv_next;
pl->pl_symtab->pt_nsyms--;
ppval = (
PLValueStruct_t **)(pl->pl_ppval);
pindex = pv->pv_pi;
ppval[pindex -
1] =
0;
break;
}
}
}
return (pv) ? &pv->pv_pbparam :
NULL;
}
NSAPI_PUBLIC pb_param *pblock_removeone(pblock *pb)
{
PListStruct_t *pl =
PBTOPL(pb);
if (pl && pl->pl_symtab) {
for (
int i =
0; i <
PLSIZENDX(pl->pl_symtab->pt_sizendx); i++) {
PLValueStruct_t *pv = pl->pl_symtab->pt_hash[i];
if (pv) {
pl->pl_symtab->pt_hash[i] = pv->pv_next;
pl->pl_symtab->pt_nsyms--;
PLValueStruct_t **ppval = (
PLValueStruct_t**)pl->pl_ppval;
ppval[pv->pv_pi -
1] =
0;
return &pv->pv_pbparam;
}
}
}
return NULL;
}
int _verify_pbstr(
const char *str)
{
const char *cp;
const char *scp;
int np;
int state;
int quote;
for(cp = str, np =
0, state =
0; *cp; ) {
switch (state) {
case 0:
while (*cp && isspace(*cp)) ++cp;
if (*cp ==
'=') {
return -
1;
}
if (*cp) state =
1;
break;
case 1:
scp = cp;
while (*cp && (*cp !=
'=') && !isspace(*cp)) ++cp;
if (*cp ==
'=') ++cp;
else cp = scp;
state =
2;
break;
case 2:
quote =
0;
if (*cp ==
'\"') {
quote =
1;
++cp;
}
for (;;) {
if (*cp ==
'\\') {
++cp;
if (*cp ==
0) {
return -
1;
}
}
else if (*cp ==
'\"') {
if (!quote) {
return -
1;
}
++np;
++cp;
quote =
0;
state =
0;
break;
}
else if (!quote && (!*cp || isspace(*cp))) {
++np;
if (*cp) ++cp;
state =
0;
break;
}
else if (*cp ==
0) {
return -
1;
}
++cp;
}
if (quote) {
return -
1;
}
break;
}
}
return (state ==
0) ? np : -
1;
}
NSAPI_PUBLIC int
INTpblock_str2pblock_lowercasename(
const char *str, pblock *pb)
{
return _pblock_str2pblock(str, pb,
PR_TRUE);
}
NSAPI_PUBLIC int pblock_str2pblock(
const char *str, pblock *pb)
{
return _pblock_str2pblock(str, pb,
PR_FALSE);
}
int
_pblock_str2pblock(
const char* str, pblock* pb, PRBool lowerCase)
{
char *cpy;
char *cp;
char *dp;
char *pname;
char *pvalue;
int np;
int quote;
int state;
char numbuf[
UTIL_ITOA_SIZE];
if((np = _verify_pbstr(str)) <
1)
return -
1;
while (*str && isspace(*str)) ++str;
cpy =
STRDUP(str);
for (np =
0, cp = cpy, state =
0; *cp; ) {
switch (state) {
case 0:
while (*cp && isspace(*cp)) ++cp;
if (*cp) state =
1;
break;
case 1:
pname = cp;
while (*cp && (*cp !=
'=') && !isspace(*cp)) ++cp;
if (*cp ==
'=') {
*cp++ =
0;
}
else {
cp = pname;
pname = numbuf;
util_itoa(np+
1, numbuf);
}
state =
2;
break;
case 2:
quote =
0;
if (*cp ==
'\"') {
quote =
1;
++cp;
}
for (pvalue = cp, dp = cp; ; ++cp, ++dp) {
if (*cp ==
'\\') {
++cp;
}
else if (*cp ==
'\"') {
++np;
++cp;
*dp =
0;
quote =
0;
state =
0;
break;
}
else if (!quote && ((*cp ==
0) || isspace(*cp))) {
++np;
if (*cp !=
0) {
++cp;
}
*dp =
0;
state =
0;
break;
}
if (cp != dp) *dp = *cp;
}
if (lowerCase ==
PR_TRUE) {
for (
char* p = pname; *p; p++) {
*p = tolower(*p);
}
}
pblock_nvinsert(pname, pvalue, pb);
break;
}
}
FREE(cpy);
return np;
}
NSAPI_PUBLIC char *pblock_pblock2str(
const pblock *pb,
char *str)
{
char *s = str, *t, *u;
PListStruct_t *pl =
PBTOPL(pb);
PLValueStruct_t **ppval;
PLValueStruct_t *pv;
int i;
int sl;
int xlen;
ppval = (
PLValueStruct_t **)(pl->pl_ppval);
for (i =
0, xlen =
0; i < pl->pl_initpi; ++i) {
pv = ppval[i];
if (pv && pv->pv_name) {
int ln = strlen(pv->pv_name);
int lv = strlen((
char *)(pv->pv_value));
for (t = (
char *)(pv->pv_value); *t; ++t) {
if ((*t ==
'\"') || (*t ==
'\\')) ++lv;
}
xlen += (ln + lv +
4);
}
}
if (!s) {
s = (
char *)
MALLOC(xlen);
s[
0] =
'\0';
t = &s[
0];
sl = xlen;
}
else {
sl = strlen(s);
t = &s[sl];
sl += xlen;
s = (
char *)
REALLOC(s, sl);
}
for (i =
0; i < pl->pl_initpi; ++i) {
pv = ppval[i];
if (pv && pv->pv_name) {
if (t != s) *t++ =
' ';
for (u = pv->pv_name; *u; ) *t++ = *u++;
*t++ =
'=';
*t++ =
'\"';
for (u = (
char *)(pv->pv_value); *u; ) {
if ((*u ==
'\\') || (*u ==
'\"')) *t++ =
'\\';
*t++ = *u++;
}
*t++ =
'\"';
*t =
'\0';
}
}
return s;
}
NSAPI_PUBLIC int pblock_copy(
const pblock *src, pblock *dst)
{
PListStruct_t *pl =
PBTOPL(src);
PLValueStruct_t **ppval;
PLValueStruct_t *pv;
int rv =
0;
int i;
ppval = (
PLValueStruct_t **)(pl->pl_ppval);
for (i =
0; i < pl->pl_initpi; ++i) {
pv = ppval[i];
if (pv) {
if (pv->pv_pbkey) {
if (pv->pv_pbkey != pb_key_magnus_internal) {
if (!pblock_kvinsert(pv->pv_pbkey, (
char *)(pv->pv_value), strlen(pv->pv_value), dst))
rv = -
1;
}
}
else {
if (!pblock_nvinsert(pv->pv_name, (
char *)(pv->pv_value), dst))
rv = -
1;
}
}
}
return rv;
}
NSAPI_PUBLIC pblock *pblock_dup(
const pblock *src)
{
pblock *dst;
if (!src)
return NULL;
if ( (dst = pblock_create(src->hsize)) )
pblock_copy(src, dst);
return dst;
}
NSAPI_PUBLIC char **pblock_pb2env(
const pblock *pb,
char **env)
{
PListStruct_t *pl =
PBTOPL(pb);
PLValueStruct_t **ppval;
PLValueStruct_t *pv;
int i;
int nval;
int pos;
ppval = (
PLValueStruct_t **)(pl->pl_ppval);
for (i =
0, nval =
0; i < pl->pl_initpi; ++i) {
if (ppval[i]) ++nval;
}
env = util_env_create(env, nval, &pos);
for (i =
0; i < pl->pl_initpi; ++i) {
pv = ppval[i];
if (pv) {
env[pos++] = util_env_str(pv->pv_name, (
char *)(pv->pv_value));
}
}
env[pos] =
NULL;
return env;
}
NSAPI_PUBLIC char * pblock_replace(
const char *name,
char * new_value, pblock *pb)
{
PListStruct_t *pl =
PBTOPL(pb);
pb_param *pp = pblock_find(name, pb);
if (!pp)
return NULL;
pool_free(pl->pl_mempool, pp->value);
pp->value = new_value;
return new_value;
}
NSAPI_PUBLIC void pblock_nvreplace (
const char *name,
const char *value, pblock *pb)
{
PListStruct_t *pl =
PBTOPL(pb);
pb_param *pp = pblock_find(name, pb);
if (pp) {
pool_free(pl->pl_mempool, pp->value);
pp->value = pool_strdup(pl->pl_mempool, value);
}
else {
pblock_nvinsert(name, value, pb);
}
}
NSAPI_PUBLIC void pblock_kvreplace(
const pb_key *key,
const char *value,
int valuelen, pblock *pb)
{
PListStruct_t *pl =
PBTOPL(pb);
pb_param *pp = pblock_findkey(key, pb);
if (pp) {
pool_free(pl->pl_mempool, pp->value);
pp->value = (
char*)pool_malloc(pl->pl_mempool, valuelen +
1);
memcpy(pp->value, value, valuelen +
1);
}
else {
pblock_kvinsert(key, value, valuelen, pb);
}
}