http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/a5850716/proton-c/src/extra/scanner.c ---------------------------------------------------------------------- diff --git a/proton-c/src/extra/scanner.c b/proton-c/src/extra/scanner.c new file mode 100644 index 0000000..beb7322 --- /dev/null +++ b/proton-c/src/extra/scanner.c @@ -0,0 +1,399 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +#include "scanner.h" + +#include "platform/platform.h" + +#include <proton/error.h> +#ifndef __cplusplus +#include <stdbool.h> +#endif +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#define ERROR_SIZE (1024) + +struct pn_scanner_t { + const char *input; + const char *position; + pn_token_t token; + char *atoms; + size_t size; + size_t capacity; + pn_error_t *error; +}; + +static const char *pni_token_type(pn_token_type_t type) +{ + switch (type) + { + case PN_TOK_LBRACE: return "LBRACE"; + case PN_TOK_RBRACE: return "RBRACE"; + case PN_TOK_LBRACKET: return "LBRACKET"; + case PN_TOK_RBRACKET: return "RBRACKET"; + case PN_TOK_EQUAL: return "EQUAL"; + case PN_TOK_COMMA: return "COMMA"; + case PN_TOK_POS: return "POS"; + case PN_TOK_NEG: return "NEG"; + case PN_TOK_DOT: return "DOT"; + case PN_TOK_AT: return "AT"; + case PN_TOK_DOLLAR: return "DOLLAR"; + case PN_TOK_BINARY: return "BINARY"; + case PN_TOK_STRING: return "STRING"; + case PN_TOK_SYMBOL: return "SYMBOL"; + case PN_TOK_ID: return "ID"; + case PN_TOK_FLOAT: return "FLOAT"; + case PN_TOK_INT: return "INT"; + case PN_TOK_TRUE: return "TRUE"; + case PN_TOK_FALSE: return "FALSE"; + case PN_TOK_NULL: return "NULL"; + case PN_TOK_EOS: return "EOS"; + case PN_TOK_ERR: return "ERR"; + default: return "<UNKNOWN>"; + } +} + +pn_scanner_t *pn_scanner() +{ + pn_scanner_t *scanner = (pn_scanner_t *) malloc(sizeof(pn_scanner_t)); + if (scanner) { + scanner->input = NULL; + scanner->error = pn_error(); + } + return scanner; +} + +void pn_scanner_free(pn_scanner_t *scanner) +{ + if (scanner) { + pn_error_free(scanner->error); + free(scanner); + } +} + +pn_token_t pn_scanner_token(pn_scanner_t *scanner) +{ + if (scanner) { + return scanner->token; + } else { + pn_token_t tok = {PN_TOK_ERR, 0, (size_t)0}; + return tok; + } +} + +void pn_scanner_line_info(pn_scanner_t *scanner, int *line, int *col) +{ + *line = 1; + *col = 0; + + for (const char *c = scanner->input; *c && c <= scanner->token.start; c++) { + if (*c == '\n') { + *line += 1; + *col = -1; + } else { + *col += 1; + } + } +} + +int pn_scanner_err(pn_scanner_t *scanner, int code, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + int err = pn_scanner_verr(scanner, code, fmt, ap); + va_end(ap); + return err; +} + +int pn_scanner_verr(pn_scanner_t *scanner, int code, const char *fmt, va_list ap) +{ + char error[ERROR_SIZE]; + + int line, col; + pn_scanner_line_info(scanner, &line, &col); + int size = scanner->token.size; + int ln = pni_snprintf(error, ERROR_SIZE, + "input line %i column %i %s:'%.*s': ", line, col, + pni_token_type(scanner->token.type), + size, scanner->token.start); + if (ln >= ERROR_SIZE) { + return pn_scanner_err(scanner, code, "error info truncated"); + } else if (ln < 0) { + error[0] = '\0'; + } + + int n = pni_snprintf(error + ln, ERROR_SIZE - ln, fmt, ap); + + if (n >= ERROR_SIZE - ln) { + return pn_scanner_err(scanner, code, "error info truncated"); + } else if (n < 0) { + error[0] = '\0'; + } + + return pn_error_set(scanner->error, code, error); +} + +int pn_scanner_errno(pn_scanner_t *scanner) +{ + return pn_error_code(scanner->error); +} + +const char *pn_scanner_error(pn_scanner_t *scanner) +{ + return pn_error_text(scanner->error); +} + +static void pni_scanner_emit(pn_scanner_t *scanner, pn_token_type_t type, const char *start, size_t size) +{ + scanner->token.type = type; + scanner->token.start = start; + scanner->token.size = size; +} + +static int pni_scanner_quoted(pn_scanner_t *scanner, const char *str, int start, + pn_token_type_t type) +{ + bool escape = false; + + for (int i = start; true; i++) { + char c = str[i]; + if (escape) { + escape = false; + } else { + switch (c) { + case '\0': + case '"': + pni_scanner_emit(scanner, c ? type : PN_TOK_ERR, + str, c ? i + 1 : i); + return c ? 0 : pn_scanner_err(scanner, PN_ERR, "missmatched quote"); + case '\\': + escape = true; + break; + } + } + } +} + +static int pni_scanner_binary(pn_scanner_t *scanner, const char *str) +{ + return pni_scanner_quoted(scanner, str, 2, PN_TOK_BINARY); +} + +static int pni_scanner_string(pn_scanner_t *scanner, const char *str) +{ + return pni_scanner_quoted(scanner, str, 1, PN_TOK_STRING); +} + +static int pni_scanner_alpha_end(pn_scanner_t *scanner, const char *str, int start) +{ + for (int i = start; true; i++) { + char c = str[i]; + if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))) { + return i; + } + } +} + +static int pni_scanner_alpha(pn_scanner_t *scanner, const char *str) +{ + int n = pni_scanner_alpha_end(scanner, str, 0); + pn_token_type_t type; + if (!strncmp(str, "true", n)) { + type = PN_TOK_TRUE; + } else if (!strncmp(str, "false", n)) { + type = PN_TOK_FALSE; + } else if (!strncmp(str, "null", n)) { + type = PN_TOK_NULL; + } else { + type = PN_TOK_ID; + } + + pni_scanner_emit(scanner, type, str, n); + return 0; +} + +static int pni_scanner_symbol(pn_scanner_t *scanner, const char *str) +{ + char c = str[1]; + + if (c == '"') { + return pni_scanner_quoted(scanner, str, 2, PN_TOK_SYMBOL); + } else { + int n = pni_scanner_alpha_end(scanner, str, 1); + pni_scanner_emit(scanner, PN_TOK_SYMBOL, str, n); + return 0; + } +} + +static int pni_scanner_number(pn_scanner_t *scanner, const char *str) +{ + bool dot = false; + bool exp = false; + + int i = 0; + + if (str[i] == '+' || str[i] == '-') { + i++; + } + + for ( ; true; i++) { + char c = str[i]; + switch (c) { + case '0': case '1': case '2': case '3': case '4': case '5': case '6': + case '7': case '8': case '9': + continue; + case '.': + if (dot) { + pni_scanner_emit(scanner, PN_TOK_FLOAT, str, i); + return 0; + } else { + dot = true; + } + continue; + case 'e': + case 'E': + if (exp) { + pni_scanner_emit(scanner, PN_TOK_FLOAT, str, i); + return 0; + } else { + dot = true; + exp = true; + if (str[i+1] == '+' || str[i+1] == '-') { + i++; + } + continue; + } + default: + if (dot || exp) { + pni_scanner_emit(scanner, PN_TOK_FLOAT, str, i); + return 0; + } else { + pni_scanner_emit(scanner, PN_TOK_INT, str, i); + return 0; + } + } + } +} + +static int pni_scanner_single(pn_scanner_t *scanner, const char *str, pn_token_type_t type) +{ + pni_scanner_emit(scanner, type, str, 1); + return 0; +} + +int pn_scanner_start(pn_scanner_t *scanner, const char *input) +{ + if (!scanner || !input) return PN_ARG_ERR; + scanner->input = input; + scanner->position = input; + return pn_scanner_scan(scanner); +} + +int pn_scanner_scan(pn_scanner_t *scanner) +{ + const char *str = scanner->position; + char n; + + for (char c; true; str++) { + c = *str; + switch (c) + { + case '{': + return pni_scanner_single(scanner, str, PN_TOK_LBRACE); + case '}': + return pni_scanner_single(scanner, str, PN_TOK_RBRACE); + case'[': + return pni_scanner_single(scanner, str, PN_TOK_LBRACKET); + case ']': + return pni_scanner_single(scanner, str, PN_TOK_RBRACKET); + case '=': + return pni_scanner_single(scanner, str, PN_TOK_EQUAL); + case ',': + return pni_scanner_single(scanner, str, PN_TOK_COMMA); + case '.': + n = *(str+1); + if ((n >= '0' && n <= '9')) { + return pni_scanner_number(scanner, str); + } else { + return pni_scanner_single(scanner, str, PN_TOK_DOT); + } + case '@': + return pni_scanner_single(scanner, str, PN_TOK_AT); + case '$': + return pni_scanner_single(scanner, str, PN_TOK_DOLLAR); + case '-': + n = *(str+1); + if ((n >= '0' && n <= '9') || n == '.') { + return pni_scanner_number(scanner, str); + } else { + return pni_scanner_single(scanner, str, PN_TOK_NEG); + } + case '+': + n = *(str+1); + if ((n >= '0' && n <= '9') || n == '.') { + return pni_scanner_number(scanner, str); + } else { + return pni_scanner_single(scanner, str, PN_TOK_POS); + } + case ' ': case '\t': case '\r': case '\v': case '\f': case '\n': + break; + case '0': case '1': case '2': case '3': case '4': case '5': case '6': + case '7': case '8': case '9': + return pni_scanner_number(scanner, str); + case ':': + return pni_scanner_symbol(scanner, str); + case '"': + return pni_scanner_string(scanner, str); + case 'b': + if (str[1] == '"') { + return pni_scanner_binary(scanner, str); + } + case 'a': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': + case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': + case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': + case 'w': case 'x': case 'y': case 'z': case 'A': case 'B': case 'C': + case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': + case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': + case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': + case 'Y': case 'Z': + return pni_scanner_alpha(scanner, str); + case '\0': + pni_scanner_emit(scanner, PN_TOK_EOS, str, 0); + return PN_EOS; + default: + pni_scanner_emit(scanner, PN_TOK_ERR, str, 1); + return pn_scanner_err(scanner, PN_ERR, "illegal character"); + } + } +} + +int pn_scanner_shift(pn_scanner_t *scanner) +{ + scanner->position = scanner->token.start + scanner->token.size; + int err = pn_scanner_scan(scanner); + if (err == PN_EOS) { + return 0; + } else { + return err; + } +}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/a5850716/proton-c/src/extra/scanner.h ---------------------------------------------------------------------- diff --git a/proton-c/src/extra/scanner.h b/proton-c/src/extra/scanner.h new file mode 100644 index 0000000..218babe --- /dev/null +++ b/proton-c/src/extra/scanner.h @@ -0,0 +1,74 @@ +#ifndef PROTON_SCANNER_H +#define PROTON_SCANNER_H 1 + +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +#include <proton/import_export.h> +#include <stddef.h> +#include <stdarg.h> + +typedef enum { + PN_TOK_LBRACE, + PN_TOK_RBRACE, + PN_TOK_LBRACKET, + PN_TOK_RBRACKET, + PN_TOK_EQUAL, + PN_TOK_COMMA, + PN_TOK_POS, + PN_TOK_NEG, + PN_TOK_DOT, + PN_TOK_AT, + PN_TOK_DOLLAR, + PN_TOK_BINARY, + PN_TOK_STRING, + PN_TOK_SYMBOL, + PN_TOK_ID, + PN_TOK_FLOAT, + PN_TOK_INT, + PN_TOK_TRUE, + PN_TOK_FALSE, + PN_TOK_NULL, + PN_TOK_EOS, + PN_TOK_ERR +} pn_token_type_t; + +typedef struct pn_scanner_t pn_scanner_t; + +typedef struct { + pn_token_type_t type; + const char *start; + size_t size; +} pn_token_t; + +PN_EXTERN pn_scanner_t *pn_scanner(void); +PN_EXTERN void pn_scanner_free(pn_scanner_t *scanner); +PN_EXTERN pn_token_t pn_scanner_token(pn_scanner_t *scanner); +PN_EXTERN int pn_scanner_err(pn_scanner_t *scanner, int code, const char *fmt, ...); +PN_EXTERN int pn_scanner_verr(pn_scanner_t *scanner, int code, const char *fmt, va_list ap); +PN_EXTERN void pn_scanner_line_info(pn_scanner_t *scanner, int *line, int *col); +PN_EXTERN int pn_scanner_errno(pn_scanner_t *scanner); +PN_EXTERN const char *pn_scanner_error(pn_scanner_t *scanner); +PN_EXTERN int pn_scanner_start(pn_scanner_t *scanner, const char *input); +PN_EXTERN int pn_scanner_scan(pn_scanner_t *scanner); +PN_EXTERN int pn_scanner_shift(pn_scanner_t *scanner); + +#endif /* scanner.h */ http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/a5850716/proton-c/src/extra/url.c ---------------------------------------------------------------------- diff --git a/proton-c/src/extra/url.c b/proton-c/src/extra/url.c new file mode 100644 index 0000000..c1ce628 --- /dev/null +++ b/proton-c/src/extra/url.c @@ -0,0 +1,272 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +#include "proton/url.h" +#include "proton/object.h" + +#include "core/util.h" + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> + + +/** URL-encode src and append to dst. */ +static void pni_urlencode(pn_string_t *dst, const char* src) { + static const char *bad = "@:/"; + + if (!src) return; + const char *i = src; + const char *j = strpbrk(i, bad); + while (j) { + pn_string_addf(dst, "%.*s", (int)(j-i), i); + pn_string_addf(dst, "%%%02X", (int)*j); + i = j + 1; + j = strpbrk(i, bad); + } + pn_string_addf(dst, "%s", i); +} + +// Low level url parser +static void pni_urldecode(const char *src, char *dst) +{ + const char *in = src; + char *out = dst; + while (*in != '\0') + { + if ('%' == *in) + { + if ((in[1] != '\0') && (in[2] != '\0')) + { + char esc[3]; + esc[0] = in[1]; + esc[1] = in[2]; + esc[2] = '\0'; + unsigned long d = strtoul(esc, NULL, 16); + *out = (char)d; + in += 3; + out++; + } + else + { + *out = *in; + in++; + out++; + } + } + else + { + *out = *in; + in++; + out++; + } + } + *out = '\0'; +} + +void pni_parse_url(char *url, char **scheme, char **user, char **pass, char **host, char **port, char **path) +{ + if (!url) return; + + char *slash = strchr(url, '/'); + + if (slash && slash>url) { + char *scheme_end = strstr(slash-1, "://"); + + if (scheme_end && scheme_end<slash) { + *scheme_end = '\0'; + *scheme = url; + url = scheme_end + 3; + slash = strchr(url, '/'); + } + } + + if (slash) { + *slash = '\0'; + *path = slash + 1; + } + + char *at = strchr(url, '@'); + if (at) { + *at = '\0'; + char *up = url; + *user = up; + url = at + 1; + char *colon = strchr(up, ':'); + if (colon) { + *colon = '\0'; + *pass = colon + 1; + } + } + + *host = url; + char *open = (*url == '[') ? url : 0; + if (open) { + char *close = strchr(open, ']'); + if (close) { + *host = open + 1; + *close = '\0'; + url = close + 1; + } + } + + char *colon = strchr(url, ':'); + if (colon) { + *colon = '\0'; + *port = colon + 1; + } + + if (*user) pni_urldecode(*user, *user); + if (*pass) pni_urldecode(*pass, *pass); +} + +struct pn_url_t { + char *scheme; + char *username; + char *password; + char *host; + char *port; + char *path; + pn_string_t *str; +}; + +/** Internal use only, returns the pn_string_t. Public function is pn_url_str() */ +static pn_string_t *pn_url_string(pn_url_t* url) +{ + pn_url_str(url); /* Make sure str is up to date */ + return url->str; +} + +static void pn_url_finalize(void *object) +{ + pn_url_t *url = (pn_url_t *) object; + pn_url_clear(url); + pn_free(url->str); +} + +static uintptr_t pn_url_hashcode(void *object) +{ + pn_url_t *url = (pn_url_t *) object; + return pn_hashcode(pn_url_string(url)); +} + +static intptr_t pn_url_compare(void *oa, void *ob) +{ + pn_url_t *a = (pn_url_t *) oa; + pn_url_t *b = (pn_url_t *) ob; + return pn_compare(pn_url_string(a), pn_url_string(b)); +} + + +static int pn_url_inspect(void *obj, pn_string_t *dst) +{ + pn_url_t *url = (pn_url_t *) obj; + int err = 0; + err = pn_string_addf(dst, "Url("); if (err) return err; + err = pn_inspect(pn_url_string(url), dst); if (err) return err; + return pn_string_addf(dst, ")"); +} + +#define pn_url_initialize NULL + + +pn_url_t *pn_url() { + static const pn_class_t clazz = PN_CLASS(pn_url); + pn_url_t *url = (pn_url_t*) pn_class_new(&clazz, sizeof(pn_url_t)); + if (!url) return NULL; + memset(url, 0, sizeof(*url)); + url->str = pn_string(NULL); + return url; +} + +/** Parse a string URL as a pn_url_t. + *@param[in] url A URL string. + *@return The parsed pn_url_t or NULL if url is not a valid URL string. + */ +pn_url_t *pn_url_parse(const char *str) { + if (!str || !*str) /* Empty string or NULL is illegal. */ + return NULL; + + pn_url_t *url = pn_url(); + char *str2 = pn_strdup(str); + pni_parse_url(str2, &url->scheme, &url->username, &url->password, &url->host, &url->port, &url->path); + url->scheme = pn_strdup(url->scheme); + url->username = pn_strdup(url->username); + url->password = pn_strdup(url->password); + url->host = (url->host && !*url->host) ? NULL : pn_strdup(url->host); + url->port = pn_strdup(url->port); + url->path = pn_strdup(url->path); + + free(str2); + return url; +} + +/** Free a URL */ +void pn_url_free(pn_url_t *url) { pn_free(url); } + +/** Clear the contents of the URL. */ +void pn_url_clear(pn_url_t *url) { + pn_url_set_scheme(url, NULL); + pn_url_set_username(url, NULL); + pn_url_set_password(url, NULL); + pn_url_set_host(url, NULL); + pn_url_set_port(url, NULL); + pn_url_set_path(url, NULL); + pn_string_clear(url->str); +} + +/** Return the string form of a URL. */ +const char *pn_url_str(pn_url_t *url) { + if (pn_string_get(url->str) == NULL) { + pn_string_set(url->str, ""); + if (url->scheme) pn_string_addf(url->str, "%s://", url->scheme); + if (url->username) pni_urlencode(url->str, url->username); + if (url->password) { + pn_string_addf(url->str, ":"); + pni_urlencode(url->str, url->password); + } + if (url->username || url->password) pn_string_addf(url->str, "@"); + if (url->host) { + if (strchr(url->host, ':')) pn_string_addf(url->str, "[%s]", url->host); + else pn_string_addf(url->str, "%s", url->host); + } + if (url->port) pn_string_addf(url->str, ":%s", url->port); + if (url->path) pn_string_addf(url->str, "/%s", url->path); + } + return pn_string_get(url->str); +} + +const char *pn_url_get_scheme(pn_url_t *url) { return url->scheme; } +const char *pn_url_get_username(pn_url_t *url) { return url->username; } +const char *pn_url_get_password(pn_url_t *url) { return url->password; } +const char *pn_url_get_host(pn_url_t *url) { return url->host; } +const char *pn_url_get_port(pn_url_t *url) { return url->port; } +const char *pn_url_get_path(pn_url_t *url) { return url->path; } + +#define SET(part) free(url->part); url->part = pn_strdup(part); pn_string_clear(url->str) +void pn_url_set_scheme(pn_url_t *url, const char *scheme) { SET(scheme); } +void pn_url_set_username(pn_url_t *url, const char *username) { SET(username); } +void pn_url_set_password(pn_url_t *url, const char *password) { SET(password); } +void pn_url_set_host(pn_url_t *url, const char *host) { SET(host); } +void pn_url_set_port(pn_url_t *url, const char *port) { SET(port); } +void pn_url_set_path(pn_url_t *url, const char *path) { SET(path); } + + http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/a5850716/proton-c/src/framing/framing.c ---------------------------------------------------------------------- diff --git a/proton-c/src/framing/framing.c b/proton-c/src/framing/framing.c deleted file mode 100644 index 09bf4bb..0000000 --- a/proton-c/src/framing/framing.c +++ /dev/null @@ -1,103 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <stdio.h> -#include <string.h> - -#include "framing.h" - -// TODO: These are near duplicates of code in codec.c - they should be -// deduplicated. -static inline void pn_i_write16(char *bytes, uint16_t value) -{ - bytes[0] = 0xFF & (value >> 8); - bytes[1] = 0xFF & (value ); -} - - -static inline void pn_i_write32(char *bytes, uint32_t value) -{ - bytes[0] = 0xFF & (value >> 24); - bytes[1] = 0xFF & (value >> 16); - bytes[2] = 0xFF & (value >> 8); - bytes[3] = 0xFF & (value ); -} - -static inline uint16_t pn_i_read16(const char *bytes) -{ - uint16_t a = (uint8_t) bytes[0]; - uint16_t b = (uint8_t) bytes[1]; - uint16_t r = a << 8 - | b; - return r; -} - -static inline uint32_t pn_i_read32(const char *bytes) -{ - uint32_t a = (uint8_t) bytes[0]; - uint32_t b = (uint8_t) bytes[1]; - uint32_t c = (uint8_t) bytes[2]; - uint32_t d = (uint8_t) bytes[3]; - uint32_t r = a << 24 - | b << 16 - | c << 8 - | d; - return r; -} - - -ssize_t pn_read_frame(pn_frame_t *frame, const char *bytes, size_t available, uint32_t max) -{ - if (available < AMQP_HEADER_SIZE) return 0; - uint32_t size = pn_i_read32(&bytes[0]); - if (max && size > max) return PN_ERR; - if (available < size) return 0; - unsigned int doff = 4 * (uint8_t)bytes[4]; - if (doff < AMQP_HEADER_SIZE || doff > size) return PN_ERR; - - frame->size = size - doff; - frame->ex_size = doff - AMQP_HEADER_SIZE; - frame->type = bytes[5]; - frame->channel = pn_i_read16(&bytes[6]); - frame->extended = bytes + AMQP_HEADER_SIZE; - frame->payload = bytes + doff; - - return size; -} - -size_t pn_write_frame(char *bytes, size_t available, pn_frame_t frame) -{ - size_t size = AMQP_HEADER_SIZE + frame.ex_size + frame.size; - if (size <= available) - { - pn_i_write32(&bytes[0], size); - int doff = (frame.ex_size + AMQP_HEADER_SIZE - 1)/4 + 1; - bytes[4] = doff; - bytes[5] = frame.type; - pn_i_write16(&bytes[6], frame.channel); - - memmove(bytes + AMQP_HEADER_SIZE, frame.extended, frame.ex_size); - memmove(bytes + 4*doff, frame.payload, frame.size); - return size; - } else { - return 0; - } -} http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/a5850716/proton-c/src/framing/framing.h ---------------------------------------------------------------------- diff --git a/proton-c/src/framing/framing.h b/proton-c/src/framing/framing.h deleted file mode 100644 index 6033867..0000000 --- a/proton-c/src/framing/framing.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef PROTON_FRAMING_H -#define PROTON_FRAMING_H 1 - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <proton/import_export.h> -#include <proton/type_compat.h> -#include <proton/error.h> - -#ifdef __cplusplus -extern "C" { -#endif - -#define AMQP_HEADER_SIZE (8) -#define AMQP_MIN_MAX_FRAME_SIZE ((uint32_t)512) // minimum allowable max-frame - -typedef struct { - uint8_t type; - uint16_t channel; - size_t ex_size; - const char *extended; - size_t size; - const char *payload; -} pn_frame_t; - -ssize_t pn_read_frame(pn_frame_t *frame, const char *bytes, size_t available, uint32_t max); -size_t pn_write_frame(char *bytes, size_t size, pn_frame_t frame); - -#ifdef __cplusplus -} -#endif - -#endif /* framing.h */ http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/a5850716/proton-c/src/handlers/iohandler.c ---------------------------------------------------------------------- diff --git a/proton-c/src/handlers/iohandler.c b/proton-c/src/handlers/iohandler.c index 9154884..db18c0c 100644 --- a/proton-c/src/handlers/iohandler.c +++ b/proton-c/src/handlers/iohandler.c @@ -19,8 +19,11 @@ * */ +#include "reactor/io.h" +#include "reactor/reactor.h" +#include "reactor/selector.h" + #include <proton/handlers.h> -#include <proton/selector.h> #include <proton/transport.h> #include <assert.h> @@ -62,7 +65,7 @@ static void pn_iodispatch(pn_iohandler_t *handler, pn_event_t *event, pn_event_t pn_record_t *record = pn_reactor_attachments(reactor); pn_selector_t *selector = (pn_selector_t *) pn_record_get(record, PN_SELECTOR); if (!selector) { - selector = pn_io_selector(pn_reactor_io(reactor)); + selector = pn_io_selector(pni_reactor_io(reactor)); pn_record_def(record, PN_SELECTOR, PN_OBJECT); pn_record_set(record, PN_SELECTOR, selector); pn_decref(selector); http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/a5850716/proton-c/src/libqpid-proton-core.pc.in ---------------------------------------------------------------------- diff --git a/proton-c/src/libqpid-proton-core.pc.in b/proton-c/src/libqpid-proton-core.pc.in new file mode 100644 index 0000000..ff99108 --- /dev/null +++ b/proton-c/src/libqpid-proton-core.pc.in @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +prefix=@PREFIX@ +exec_prefix=@EXEC_PREFIX@ +libdir=@LIBDIR@ +includedir=@INCLUDEDIR@ + +Name: Proton Core +Description: Qpid Proton C core protocol library +Version: @PN_VERSION@ +URL: http://qpid.apache.org/proton/ +Libs: -L${libdir} -lqpid-proton-core +Cflags: -I${includedir} http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/a5850716/proton-c/src/log.c ---------------------------------------------------------------------- diff --git a/proton-c/src/log.c b/proton-c/src/log.c deleted file mode 100644 index b92a99a..0000000 --- a/proton-c/src/log.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include <proton/log.h> -#include <proton/object.h> -#include <stdio.h> -#include "util.h" - - -static void stderr_logger(const char *message) { - fprintf(stderr, "%s\n", message); -} - -static pn_logger_t logger = stderr_logger; -static int enabled_env = -1; /* Set from environment variable. */ -static int enabled_call = -1; /* set by pn_log_enable */ - -void pn_log_enable(bool value) { - enabled_call = value; -} - -bool pn_log_enabled(void) { - if (enabled_call != -1) return enabled_call; /* Takes precedence */ - if (enabled_env == -1) - enabled_env = pn_env_bool("PN_TRACE_LOG"); - return enabled_env; -} - -void pn_log_logger(pn_logger_t new_logger) { - logger = new_logger; - if (!logger) pn_log_enable(false); -} - -void pn_vlogf_impl(const char *fmt, va_list ap) { - pn_string_t *msg = pn_string(""); - pn_string_vformat(msg, fmt, ap); - fprintf(stderr, "%s\n", pn_string_get(msg)); -} - -/**@internal - * - * Note: We check pn_log_enabled() in the pn_logf macro *before* calling - * pn_logf_impl because evaluating the arguments to that call could have - * side-effects with performance impact (e.g. calling functions to construct - * complicated messages.) It is important that a disabled log statement results - * in nothing more than a call to pn_log_enabled(). - */ -void pn_logf_impl(const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - pn_vlogf_impl(fmt, ap); - va_end(ap); -} - http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/a5850716/proton-c/src/log_private.h ---------------------------------------------------------------------- diff --git a/proton-c/src/log_private.h b/proton-c/src/log_private.h deleted file mode 100644 index 4725045..0000000 --- a/proton-c/src/log_private.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef LOG_PRIVATE_H -#define LOG_PRIVATE_H -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -/**@file - * - * Log messages that are not associated with a transport. - */ - -#include <proton/log.h> -#include <stdarg.h> - -/** Log a printf style message */ -#define pn_logf(...) \ - do { \ - if (pn_log_enabled()) \ - pn_logf_impl(__VA_ARGS__); \ - } while(0) - -/** va_list version of pn_logf */ -#define pn_vlogf(fmt, ap) \ - do { \ - if (pn_log_enabled()) \ - pn_vlogf_impl(fmt, ap); \ - } while(0) - -/** Return true if logging is enabled. */ -bool pn_log_enabled(void); - -/**@internal*/ -void pn_logf_impl(const char* fmt, ...); -/**@internal*/ -void pn_vlogf_impl(const char *fmt, va_list ap); - - - -#endif http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/a5850716/proton-c/src/message/message.c ---------------------------------------------------------------------- diff --git a/proton-c/src/message/message.c b/proton-c/src/message/message.c deleted file mode 100644 index 15d9c6c..0000000 --- a/proton-c/src/message/message.c +++ /dev/null @@ -1,861 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <proton/message.h> -#include <proton/object.h> -#include <proton/codec.h> -#include <proton/error.h> -#include <proton/parser.h> -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <assert.h> -#include "protocol.h" -#include "util.h" -#include "platform_fmt.h" - -// message - -struct pn_message_t { - pn_timestamp_t expiry_time; - pn_timestamp_t creation_time; - pn_data_t *id; - pn_string_t *user_id; - pn_string_t *address; - pn_string_t *subject; - pn_string_t *reply_to; - pn_data_t *correlation_id; - pn_string_t *content_type; - pn_string_t *content_encoding; - pn_string_t *group_id; - pn_string_t *reply_to_group_id; - - pn_data_t *data; - pn_data_t *instructions; - pn_data_t *annotations; - pn_data_t *properties; - pn_data_t *body; - - pn_error_t *error; - - pn_sequence_t group_sequence; - pn_millis_t ttl; - uint32_t delivery_count; - - uint8_t priority; - - bool durable; - bool first_acquirer; - bool inferred; -}; - -void pn_message_finalize(void *obj) -{ - pn_message_t *msg = (pn_message_t *) obj; - pn_free(msg->user_id); - pn_free(msg->address); - pn_free(msg->subject); - pn_free(msg->reply_to); - pn_free(msg->content_type); - pn_free(msg->content_encoding); - pn_free(msg->group_id); - pn_free(msg->reply_to_group_id); - pn_data_free(msg->id); - pn_data_free(msg->correlation_id); - pn_data_free(msg->data); - pn_data_free(msg->instructions); - pn_data_free(msg->annotations); - pn_data_free(msg->properties); - pn_data_free(msg->body); - pn_error_free(msg->error); -} - -int pn_message_inspect(void *obj, pn_string_t *dst) -{ - pn_message_t *msg = (pn_message_t *) obj; - int err = pn_string_addf(dst, "Message{"); - if (err) return err; - - bool comma = false; - - if (pn_string_get(msg->address)) { - err = pn_string_addf(dst, "address="); - if (err) return err; - err = pn_inspect(msg->address, dst); - if (err) return err; - err = pn_string_addf(dst, ", "); - if (err) return err; - comma = true; - } - - if (msg->durable) { - err = pn_string_addf(dst, "durable=%i, ", msg->durable); - if (err) return err; - comma = true; - } - - if (msg->priority != PN_DEFAULT_PRIORITY) { - err = pn_string_addf(dst, "priority=%i, ", msg->priority); - if (err) return err; - comma = true; - } - - if (msg->ttl) { - err = pn_string_addf(dst, "ttl=%" PRIu32 ", ", msg->ttl); - if (err) return err; - comma = true; - } - - if (msg->first_acquirer) { - err = pn_string_addf(dst, "first_acquirer=%i, ", msg->first_acquirer); - if (err) return err; - comma = true; - } - - if (msg->delivery_count) { - err = pn_string_addf(dst, "delivery_count=%" PRIu32 ", ", msg->delivery_count); - if (err) return err; - comma = true; - } - - if (pn_data_size(msg->id)) { - err = pn_string_addf(dst, "id="); - if (err) return err; - err = pn_inspect(msg->id, dst); - if (err) return err; - err = pn_string_addf(dst, ", "); - if (err) return err; - comma = true; - } - - if (pn_string_get(msg->user_id)) { - err = pn_string_addf(dst, "user_id="); - if (err) return err; - err = pn_inspect(msg->user_id, dst); - if (err) return err; - err = pn_string_addf(dst, ", "); - if (err) return err; - comma = true; - } - - if (pn_string_get(msg->subject)) { - err = pn_string_addf(dst, "subject="); - if (err) return err; - err = pn_inspect(msg->subject, dst); - if (err) return err; - err = pn_string_addf(dst, ", "); - if (err) return err; - comma = true; - } - - if (pn_string_get(msg->reply_to)) { - err = pn_string_addf(dst, "reply_to="); - if (err) return err; - err = pn_inspect(msg->reply_to, dst); - if (err) return err; - err = pn_string_addf(dst, ", "); - if (err) return err; - comma = true; - } - - if (pn_data_size(msg->correlation_id)) { - err = pn_string_addf(dst, "correlation_id="); - if (err) return err; - err = pn_inspect(msg->correlation_id, dst); - if (err) return err; - err = pn_string_addf(dst, ", "); - if (err) return err; - comma = true; - } - - if (pn_string_get(msg->content_type)) { - err = pn_string_addf(dst, "content_type="); - if (err) return err; - err = pn_inspect(msg->content_type, dst); - if (err) return err; - err = pn_string_addf(dst, ", "); - if (err) return err; - comma = true; - } - - if (pn_string_get(msg->content_encoding)) { - err = pn_string_addf(dst, "content_encoding="); - if (err) return err; - err = pn_inspect(msg->content_encoding, dst); - if (err) return err; - err = pn_string_addf(dst, ", "); - if (err) return err; - comma = true; - } - - if (msg->expiry_time) { - err = pn_string_addf(dst, "expiry_time=%" PRIi64 ", ", msg->expiry_time); - if (err) return err; - comma = true; - } - - if (msg->creation_time) { - err = pn_string_addf(dst, "creation_time=%" PRIi64 ", ", msg->creation_time); - if (err) return err; - comma = true; - } - - if (pn_string_get(msg->group_id)) { - err = pn_string_addf(dst, "group_id="); - if (err) return err; - err = pn_inspect(msg->group_id, dst); - if (err) return err; - err = pn_string_addf(dst, ", "); - if (err) return err; - comma = true; - } - - if (msg->group_sequence) { - err = pn_string_addf(dst, "group_sequence=%" PRIi32 ", ", msg->group_sequence); - if (err) return err; - comma = true; - } - - if (pn_string_get(msg->reply_to_group_id)) { - err = pn_string_addf(dst, "reply_to_group_id="); - if (err) return err; - err = pn_inspect(msg->reply_to_group_id, dst); - if (err) return err; - err = pn_string_addf(dst, ", "); - if (err) return err; - comma = true; - } - - if (msg->inferred) { - err = pn_string_addf(dst, "inferred=%i, ", msg->inferred); - if (err) return err; - comma = true; - } - - if (pn_data_size(msg->instructions)) { - err = pn_string_addf(dst, "instructions="); - if (err) return err; - err = pn_inspect(msg->instructions, dst); - if (err) return err; - err = pn_string_addf(dst, ", "); - if (err) return err; - comma = true; - } - - if (pn_data_size(msg->annotations)) { - err = pn_string_addf(dst, "annotations="); - if (err) return err; - err = pn_inspect(msg->annotations, dst); - if (err) return err; - err = pn_string_addf(dst, ", "); - if (err) return err; - comma = true; - } - - if (pn_data_size(msg->properties)) { - err = pn_string_addf(dst, "properties="); - if (err) return err; - err = pn_inspect(msg->properties, dst); - if (err) return err; - err = pn_string_addf(dst, ", "); - if (err) return err; - comma = true; - } - - if (pn_data_size(msg->body)) { - err = pn_string_addf(dst, "body="); - if (err) return err; - err = pn_inspect(msg->body, dst); - if (err) return err; - err = pn_string_addf(dst, ", "); - if (err) return err; - comma = true; - } - - if (comma) { - int err = pn_string_resize(dst, pn_string_size(dst) - 2); - if (err) return err; - } - - return pn_string_addf(dst, "}"); -} - -#define pn_message_initialize NULL -#define pn_message_hashcode NULL -#define pn_message_compare NULL - -pn_message_t *pn_message() -{ - static const pn_class_t clazz = PN_CLASS(pn_message); - pn_message_t *msg = (pn_message_t *) pn_class_new(&clazz, sizeof(pn_message_t)); - msg->durable = false; - msg->priority = PN_DEFAULT_PRIORITY; - msg->ttl = 0; - msg->first_acquirer = false; - msg->delivery_count = 0; - msg->id = pn_data(1); - msg->user_id = pn_string(NULL); - msg->address = pn_string(NULL); - msg->subject = pn_string(NULL); - msg->reply_to = pn_string(NULL); - msg->correlation_id = pn_data(1); - msg->content_type = pn_string(NULL); - msg->content_encoding = pn_string(NULL); - msg->expiry_time = 0; - msg->creation_time = 0; - msg->group_id = pn_string(NULL); - msg->group_sequence = 0; - msg->reply_to_group_id = pn_string(NULL); - - msg->inferred = false; - msg->data = pn_data(16); - msg->instructions = pn_data(16); - msg->annotations = pn_data(16); - msg->properties = pn_data(16); - msg->body = pn_data(16); - - msg->error = pn_error(); - return msg; -} - -void pn_message_free(pn_message_t *msg) -{ - pn_free(msg); -} - -void pn_message_clear(pn_message_t *msg) -{ - msg->durable = false; - msg->priority = PN_DEFAULT_PRIORITY; - msg->ttl = 0; - msg->first_acquirer = false; - msg->delivery_count = 0; - pn_data_clear(msg->id); - pn_string_clear(msg->user_id); - pn_string_clear(msg->address); - pn_string_clear(msg->subject); - pn_string_clear(msg->reply_to); - pn_data_clear(msg->correlation_id); - pn_string_clear(msg->content_type); - pn_string_clear(msg->content_encoding); - msg->expiry_time = 0; - msg->creation_time = 0; - pn_string_clear(msg->group_id); - msg->group_sequence = 0; - pn_string_clear(msg->reply_to_group_id); - msg->inferred = false; - pn_data_clear(msg->data); - pn_data_clear(msg->instructions); - pn_data_clear(msg->annotations); - pn_data_clear(msg->properties); - pn_data_clear(msg->body); -} - -int pn_message_errno(pn_message_t *msg) -{ - assert(msg); - return pn_error_code(msg->error); -} - -pn_error_t *pn_message_error(pn_message_t *msg) -{ - assert(msg); - return msg->error; -} - -bool pn_message_is_inferred(pn_message_t *msg) -{ - assert(msg); - return msg->inferred; -} - -int pn_message_set_inferred(pn_message_t *msg, bool inferred) -{ - assert(msg); - msg->inferred = inferred; - return 0; -} - -bool pn_message_is_durable(pn_message_t *msg) -{ - assert(msg); - return msg->durable; -} -int pn_message_set_durable(pn_message_t *msg, bool durable) -{ - assert(msg); - msg->durable = durable; - return 0; -} - - -uint8_t pn_message_get_priority(pn_message_t *msg) -{ - assert(msg); - return msg->priority; -} -int pn_message_set_priority(pn_message_t *msg, uint8_t priority) -{ - assert(msg); - msg->priority = priority; - return 0; -} - -pn_millis_t pn_message_get_ttl(pn_message_t *msg) -{ - assert(msg); - return msg->ttl; -} -int pn_message_set_ttl(pn_message_t *msg, pn_millis_t ttl) -{ - assert(msg); - msg->ttl = ttl; - return 0; -} - -bool pn_message_is_first_acquirer(pn_message_t *msg) -{ - assert(msg); - return msg->first_acquirer; -} -int pn_message_set_first_acquirer(pn_message_t *msg, bool first) -{ - assert(msg); - msg->first_acquirer = first; - return 0; -} - -uint32_t pn_message_get_delivery_count(pn_message_t *msg) -{ - assert(msg); - return msg->delivery_count; -} -int pn_message_set_delivery_count(pn_message_t *msg, uint32_t count) -{ - assert(msg); - msg->delivery_count = count; - return 0; -} - -pn_data_t *pn_message_id(pn_message_t *msg) -{ - assert(msg); - return msg->id; -} -pn_atom_t pn_message_get_id(pn_message_t *msg) -{ - assert(msg); - return pn_data_get_atom(msg->id); -} -int pn_message_set_id(pn_message_t *msg, pn_atom_t id) -{ - assert(msg); - pn_data_rewind(msg->id); - return pn_data_put_atom(msg->id, id); -} - -static pn_bytes_t pn_string_get_bytes(pn_string_t *string) -{ - return pn_bytes(pn_string_size(string), (char *) pn_string_get(string)); -} - -static int pn_string_set_bytes(pn_string_t *string, pn_bytes_t bytes) -{ - return pn_string_setn(string, bytes.start, bytes.size); -} - -pn_bytes_t pn_message_get_user_id(pn_message_t *msg) -{ - assert(msg); - return pn_string_get_bytes(msg->user_id); -} -int pn_message_set_user_id(pn_message_t *msg, pn_bytes_t user_id) -{ - assert(msg); - return pn_string_set_bytes(msg->user_id, user_id); -} - -const char *pn_message_get_address(pn_message_t *msg) -{ - assert(msg); - return pn_string_get(msg->address); -} -int pn_message_set_address(pn_message_t *msg, const char *address) -{ - assert(msg); - return pn_string_set(msg->address, address); -} - -const char *pn_message_get_subject(pn_message_t *msg) -{ - assert(msg); - return pn_string_get(msg->subject); -} -int pn_message_set_subject(pn_message_t *msg, const char *subject) -{ - assert(msg); - return pn_string_set(msg->subject, subject); -} - -const char *pn_message_get_reply_to(pn_message_t *msg) -{ - assert(msg); - return pn_string_get(msg->reply_to); -} -int pn_message_set_reply_to(pn_message_t *msg, const char *reply_to) -{ - assert(msg); - return pn_string_set(msg->reply_to, reply_to); -} - -pn_data_t *pn_message_correlation_id(pn_message_t *msg) -{ - assert(msg); - return msg->correlation_id; -} -pn_atom_t pn_message_get_correlation_id(pn_message_t *msg) -{ - assert(msg); - return pn_data_get_atom(msg->correlation_id); -} -int pn_message_set_correlation_id(pn_message_t *msg, pn_atom_t atom) -{ - assert(msg); - pn_data_rewind(msg->correlation_id); - return pn_data_put_atom(msg->correlation_id, atom); -} - -const char *pn_message_get_content_type(pn_message_t *msg) -{ - assert(msg); - return pn_string_get(msg->content_type); -} -int pn_message_set_content_type(pn_message_t *msg, const char *type) -{ - assert(msg); - return pn_string_set(msg->content_type, type); -} - -const char *pn_message_get_content_encoding(pn_message_t *msg) -{ - assert(msg); - return pn_string_get(msg->content_encoding); -} -int pn_message_set_content_encoding(pn_message_t *msg, const char *encoding) -{ - assert(msg); - return pn_string_set(msg->content_encoding, encoding); -} - -pn_timestamp_t pn_message_get_expiry_time(pn_message_t *msg) -{ - assert(msg); - return msg->expiry_time; -} -int pn_message_set_expiry_time(pn_message_t *msg, pn_timestamp_t time) -{ - assert(msg); - msg->expiry_time = time; - return 0; -} - -pn_timestamp_t pn_message_get_creation_time(pn_message_t *msg) -{ - assert(msg); - return msg->creation_time; -} -int pn_message_set_creation_time(pn_message_t *msg, pn_timestamp_t time) -{ - assert(msg); - msg->creation_time = time; - return 0; -} - -const char *pn_message_get_group_id(pn_message_t *msg) -{ - assert(msg); - return pn_string_get(msg->group_id); -} -int pn_message_set_group_id(pn_message_t *msg, const char *group_id) -{ - assert(msg); - return pn_string_set(msg->group_id, group_id); -} - -pn_sequence_t pn_message_get_group_sequence(pn_message_t *msg) -{ - assert(msg); - return msg->group_sequence; -} -int pn_message_set_group_sequence(pn_message_t *msg, pn_sequence_t n) -{ - assert(msg); - msg->group_sequence = n; - return 0; -} - -const char *pn_message_get_reply_to_group_id(pn_message_t *msg) -{ - assert(msg); - return pn_string_get(msg->reply_to_group_id); -} -int pn_message_set_reply_to_group_id(pn_message_t *msg, const char *reply_to_group_id) -{ - assert(msg); - return pn_string_set(msg->reply_to_group_id, reply_to_group_id); -} - -int pn_message_decode(pn_message_t *msg, const char *bytes, size_t size) -{ - assert(msg && bytes && size); - - pn_message_clear(msg); - - while (size) { - pn_data_clear(msg->data); - ssize_t used = pn_data_decode(msg->data, bytes, size); - if (used < 0) - return pn_error_format(msg->error, used, "data error: %s", - pn_error_text(pn_data_error(msg->data))); - size -= used; - bytes += used; - bool scanned; - uint64_t desc; - int err = pn_data_scan(msg->data, "D?L.", &scanned, &desc); - if (err) return pn_error_format(msg->error, err, "data error: %s", - pn_error_text(pn_data_error(msg->data))); - if (!scanned) { - desc = 0; - } - - pn_data_rewind(msg->data); - pn_data_next(msg->data); - pn_data_enter(msg->data); - pn_data_next(msg->data); - - switch (desc) { - case HEADER: - err = pn_data_scan(msg->data, "D.[oBIoI]", &msg->durable, &msg->priority, - &msg->ttl, &msg->first_acquirer, &msg->delivery_count); - if (err) return pn_error_format(msg->error, err, "data error: %s", - pn_error_text(pn_data_error(msg->data))); - break; - case PROPERTIES: - { - pn_bytes_t user_id, address, subject, reply_to, ctype, cencoding, - group_id, reply_to_group_id; - pn_data_clear(msg->id); - pn_data_clear(msg->correlation_id); - err = pn_data_scan(msg->data, "D.[CzSSSCssttSIS]", msg->id, - &user_id, &address, &subject, &reply_to, - msg->correlation_id, &ctype, &cencoding, - &msg->expiry_time, &msg->creation_time, &group_id, - &msg->group_sequence, &reply_to_group_id); - if (err) return pn_error_format(msg->error, err, "data error: %s", - pn_error_text(pn_data_error(msg->data))); - err = pn_string_set_bytes(msg->user_id, user_id); - if (err) return pn_error_format(msg->error, err, "error setting user_id"); - err = pn_string_setn(msg->address, address.start, address.size); - if (err) return pn_error_format(msg->error, err, "error setting address"); - err = pn_string_setn(msg->subject, subject.start, subject.size); - if (err) return pn_error_format(msg->error, err, "error setting subject"); - err = pn_string_setn(msg->reply_to, reply_to.start, reply_to.size); - if (err) return pn_error_format(msg->error, err, "error setting reply_to"); - err = pn_string_setn(msg->content_type, ctype.start, ctype.size); - if (err) return pn_error_format(msg->error, err, "error setting content_type"); - err = pn_string_setn(msg->content_encoding, cencoding.start, - cencoding.size); - if (err) return pn_error_format(msg->error, err, "error setting content_encoding"); - err = pn_string_setn(msg->group_id, group_id.start, group_id.size); - if (err) return pn_error_format(msg->error, err, "error setting group_id"); - err = pn_string_setn(msg->reply_to_group_id, reply_to_group_id.start, - reply_to_group_id.size); - if (err) return pn_error_format(msg->error, err, "error setting reply_to_group_id"); - } - break; - case DELIVERY_ANNOTATIONS: - pn_data_narrow(msg->data); - err = pn_data_copy(msg->instructions, msg->data); - if (err) return err; - break; - case MESSAGE_ANNOTATIONS: - pn_data_narrow(msg->data); - err = pn_data_copy(msg->annotations, msg->data); - if (err) return err; - break; - case APPLICATION_PROPERTIES: - pn_data_narrow(msg->data); - err = pn_data_copy(msg->properties, msg->data); - if (err) return err; - break; - case DATA: - case AMQP_SEQUENCE: - case AMQP_VALUE: - pn_data_narrow(msg->data); - err = pn_data_copy(msg->body, msg->data); - if (err) return err; - break; - case FOOTER: - break; - default: - err = pn_data_copy(msg->body, msg->data); - if (err) return err; - break; - } - } - - pn_data_clear(msg->data); - return 0; -} - -int pn_message_encode(pn_message_t *msg, char *bytes, size_t *size) -{ - if (!msg || !bytes || !size || !*size) return PN_ARG_ERR; - pn_data_clear(msg->data); - pn_message_data(msg, msg->data); - size_t remaining = *size; - ssize_t encoded = pn_data_encode(msg->data, bytes, remaining); - if (encoded < 0) { - if (encoded == PN_OVERFLOW) { - return encoded; - } else { - return pn_error_format(msg->error, encoded, "data error: %s", - pn_error_text(pn_data_error(msg->data))); - } - } - bytes += encoded; - remaining -= encoded; - *size -= remaining; - pn_data_clear(msg->data); - return 0; -} - -int pn_message_data(pn_message_t *msg, pn_data_t *data) -{ - pn_data_clear(data); - int err = pn_data_fill(data, "DL[oB?IoI]", HEADER, msg->durable, - msg->priority, msg->ttl, msg->ttl, msg->first_acquirer, - msg->delivery_count); - if (err) - return pn_error_format(msg->error, err, "data error: %s", - pn_error_text(pn_data_error(data))); - - if (pn_data_size(msg->instructions)) { - pn_data_put_described(data); - pn_data_enter(data); - pn_data_put_ulong(data, DELIVERY_ANNOTATIONS); - pn_data_rewind(msg->instructions); - err = pn_data_append(data, msg->instructions); - if (err) - return pn_error_format(msg->error, err, "data error: %s", - pn_error_text(pn_data_error(data))); - pn_data_exit(data); - } - - if (pn_data_size(msg->annotations)) { - pn_data_put_described(data); - pn_data_enter(data); - pn_data_put_ulong(data, MESSAGE_ANNOTATIONS); - pn_data_rewind(msg->annotations); - err = pn_data_append(data, msg->annotations); - if (err) - return pn_error_format(msg->error, err, "data error: %s", - pn_error_text(pn_data_error(data))); - pn_data_exit(data); - } - - err = pn_data_fill(data, "DL[CzSSSCssttSIS]", PROPERTIES, - msg->id, - pn_string_size(msg->user_id), pn_string_get(msg->user_id), - pn_string_get(msg->address), - pn_string_get(msg->subject), - pn_string_get(msg->reply_to), - msg->correlation_id, - pn_string_get(msg->content_type), - pn_string_get(msg->content_encoding), - msg->expiry_time, - msg->creation_time, - pn_string_get(msg->group_id), - msg->group_sequence, - pn_string_get(msg->reply_to_group_id)); - if (err) - return pn_error_format(msg->error, err, "data error: %s", - pn_error_text(pn_data_error(data))); - - if (pn_data_size(msg->properties)) { - pn_data_put_described(data); - pn_data_enter(data); - pn_data_put_ulong(data, APPLICATION_PROPERTIES); - pn_data_rewind(msg->properties); - err = pn_data_append(data, msg->properties); - if (err) - return pn_error_format(msg->error, err, "data error: %s", - pn_data_error(data)); - pn_data_exit(data); - } - - if (pn_data_size(msg->body)) { - pn_data_rewind(msg->body); - pn_data_next(msg->body); - pn_type_t body_type = pn_data_type(msg->body); - pn_data_rewind(msg->body); - - pn_data_put_described(data); - pn_data_enter(data); - if (msg->inferred) { - switch (body_type) { - case PN_BINARY: - pn_data_put_ulong(data, DATA); - break; - case PN_LIST: - pn_data_put_ulong(data, AMQP_SEQUENCE); - break; - default: - pn_data_put_ulong(data, AMQP_VALUE); - break; - } - } else { - pn_data_put_ulong(data, AMQP_VALUE); - } - pn_data_append(data, msg->body); - } - return 0; -} - -pn_data_t *pn_message_instructions(pn_message_t *msg) -{ - return msg ? msg->instructions : NULL; -} - -pn_data_t *pn_message_annotations(pn_message_t *msg) -{ - return msg ? msg->annotations : NULL; -} - -pn_data_t *pn_message_properties(pn_message_t *msg) -{ - return msg ? msg->properties : NULL; -} - -pn_data_t *pn_message_body(pn_message_t *msg) -{ - return msg ? msg->body : NULL; -} http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/a5850716/proton-c/src/messenger/messenger.c ---------------------------------------------------------------------- diff --git a/proton-c/src/messenger/messenger.c b/proton-c/src/messenger/messenger.c index 64be017..264a733 100644 --- a/proton-c/src/messenger/messenger.c +++ b/proton-c/src/messenger/messenger.c @@ -27,7 +27,6 @@ #include <proton/object.h> #include <proton/sasl.h> #include <proton/session.h> -#include <proton/selector.h> #include <assert.h> #include <ctype.h> @@ -35,14 +34,17 @@ #include <string.h> #include <stdio.h> -#include "util.h" -#include "platform.h" -#include "platform_fmt.h" +#include "core/log_private.h" +#include "core/util.h" +#include "platform/platform.h" // pn_i_getpid, pn_i_now, pni_snprintf +#include "platform/platform_fmt.h" #include "store.h" -#include "transform.h" #include "subscription.h" -#include "selectable.h" -#include "log_private.h" +#include "transform.h" + +#include "reactor/io.h" +#include "reactor/selectable.h" +#include "reactor/selector.h" typedef struct pn_link_ctx_t pn_link_ctx_t; @@ -980,7 +982,7 @@ static void pn_condition_report(const char *pfx, pn_condition_t *condition) pn_condition_redirect_port(condition)); } else if (pn_condition_is_set(condition)) { char error[1024]; - snprintf(error, 1024, "(%s) %s", + pni_snprintf(error, 1024, "(%s) %s", pn_condition_get_name(condition), pn_condition_get_description(condition)); pn_error_report(pfx, error); http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/a5850716/proton-c/src/messenger/store.c ---------------------------------------------------------------------- diff --git a/proton-c/src/messenger/store.c b/proton-c/src/messenger/store.c index bdd7e24..44f24f1 100644 --- a/proton-c/src/messenger/store.c +++ b/proton-c/src/messenger/store.c @@ -28,7 +28,7 @@ #endif #include <stdlib.h> #include <string.h> -#include "util.h" +#include "core/util.h" #include "store.h" typedef struct pni_stream_t pni_stream_t; http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/a5850716/proton-c/src/messenger/store.h ---------------------------------------------------------------------- diff --git a/proton-c/src/messenger/store.h b/proton-c/src/messenger/store.h index 2ca243b..22bb94e 100644 --- a/proton-c/src/messenger/store.h +++ b/proton-c/src/messenger/store.h @@ -22,7 +22,7 @@ * */ -#include "buffer.h" +#include "core/buffer.h" typedef struct pni_store_t pni_store_t; typedef struct pni_entry_t pni_entry_t; http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/a5850716/proton-c/src/messenger/transform.h ---------------------------------------------------------------------- diff --git a/proton-c/src/messenger/transform.h b/proton-c/src/messenger/transform.h index c9350ef..3288f6c 100644 --- a/proton-c/src/messenger/transform.h +++ b/proton-c/src/messenger/transform.h @@ -22,8 +22,9 @@ * */ +#include "core/buffer.h" + #include <proton/object.h> -#include "buffer.h" typedef struct pn_transform_t pn_transform_t; http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/a5850716/proton-c/src/object/iterator.c ---------------------------------------------------------------------- diff --git a/proton-c/src/object/iterator.c b/proton-c/src/object/iterator.c deleted file mode 100644 index 61b3b8e..0000000 --- a/proton-c/src/object/iterator.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <proton/object.h> -#include <stdlib.h> -#include <assert.h> - -struct pn_iterator_t { - pn_iterator_next_t next; - size_t size; - void *state; -}; - -static void pn_iterator_initialize(void *object) -{ - pn_iterator_t *it = (pn_iterator_t *) object; - it->next = NULL; - it->size = 0; - it->state = NULL; -} - -static void pn_iterator_finalize(void *object) -{ - pn_iterator_t *it = (pn_iterator_t *) object; - free(it->state); -} - -#define CID_pn_iterator CID_pn_object -#define pn_iterator_hashcode NULL -#define pn_iterator_compare NULL -#define pn_iterator_inspect NULL - -pn_iterator_t *pn_iterator() -{ - static const pn_class_t clazz = PN_CLASS(pn_iterator); - pn_iterator_t *it = (pn_iterator_t *) pn_class_new(&clazz, sizeof(pn_iterator_t)); - return it; -} - -void *pn_iterator_start(pn_iterator_t *iterator, pn_iterator_next_t next, - size_t size) { - assert(iterator); - assert(next); - iterator->next = next; - if (iterator->size < size) { - iterator->state = realloc(iterator->state, size); - } - return iterator->state; -} - -void *pn_iterator_next(pn_iterator_t *iterator) { - assert(iterator); - if (iterator->next) { - void *result = iterator->next(iterator->state); - if (!result) iterator->next = NULL; - return result; - } else { - return NULL; - } -} http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/a5850716/proton-c/src/object/list.c ---------------------------------------------------------------------- diff --git a/proton-c/src/object/list.c b/proton-c/src/object/list.c deleted file mode 100644 index 76c70d2..0000000 --- a/proton-c/src/object/list.c +++ /dev/null @@ -1,267 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <proton/object.h> -#include <stdlib.h> -#include <assert.h> - -struct pn_list_t { - const pn_class_t *clazz; - size_t capacity; - size_t size; - void **elements; -}; - -size_t pn_list_size(pn_list_t *list) -{ - assert(list); - return list->size; -} - -void *pn_list_get(pn_list_t *list, int index) -{ - assert(list); assert(list->size); - return list->elements[index % list->size]; -} - -void pn_list_set(pn_list_t *list, int index, void *value) -{ - assert(list); assert(list->size); - void *old = list->elements[index % list->size]; - pn_class_decref(list->clazz, old); - list->elements[index % list->size] = value; - pn_class_incref(list->clazz, value); -} - -static void pni_list_ensure(pn_list_t *list, size_t capacity) -{ - assert(list); - if (list->capacity < capacity) { - size_t newcap = list->capacity; - while (newcap < capacity) { newcap *= 2; } - list->elements = (void **) realloc(list->elements, newcap * sizeof(void *)); - assert(list->elements); - list->capacity = newcap; - } -} - -int pn_list_add(pn_list_t *list, void *value) -{ - assert(list); - pni_list_ensure(list, list->size + 1); - list->elements[list->size++] = value; - pn_class_incref(list->clazz, value); - return 0; -} - -void *pn_list_pop(pn_list_t *list) -{ - assert(list); - if (list->size) { - return list->elements[--list->size]; - } else { - return NULL; - } -} - -ssize_t pn_list_index(pn_list_t *list, void *value) -{ - for (size_t i = 0; i < list->size; i++) { - if (pn_class_equals(list->clazz, list->elements[i], value)) { - return i; - } - } - - return -1; -} - -bool pn_list_remove(pn_list_t *list, void *value) -{ - assert(list); - ssize_t idx = pn_list_index(list, value); - if (idx < 0) { - return false; - } else { - pn_list_del(list, idx, 1); - } - - return true; -} - -void pn_list_del(pn_list_t *list, int index, int n) -{ - assert(list); - if (!list->size) { return; } - index %= list->size; - - for (int i = 0; i < n; i++) { - pn_class_decref(list->clazz, list->elements[index + i]); - } - - size_t slide = list->size - (index + n); - for (size_t i = 0; i < slide; i++) { - list->elements[index + i] = list->elements[index + n + i]; - } - - list->size -= n; -} - -void pn_list_clear(pn_list_t *list) -{ - assert(list); - pn_list_del(list, 0, list->size); -} - -void pn_list_minpush(pn_list_t *list, void *value) -{ - assert(list); - pn_list_add(list, value); - // we use one based indexing for the heap - void **heap = list->elements - 1; - int now = list->size; - while (now > 1 && pn_class_compare(list->clazz, heap[now/2], value) > 0) { - heap[now] = heap[now/2]; - now /= 2; - } - heap[now] = value; -} - -void *pn_list_minpop(pn_list_t *list) -{ - assert(list); - // we use one based indexing for the heap - void **heap = list->elements - 1; - void *min = heap[1]; - void *last = pn_list_pop(list); - int size = pn_list_size(list); - int now, child; - for (now = 1; now*2 <= size; now = child) { - child = now*2; - if (child != size && pn_class_compare(list->clazz, heap[child], heap[child + 1]) > 0) { - child++; - } - if (pn_class_compare(list->clazz, last, heap[child]) > 0) { - heap[now] = heap[child]; - } else { - break; - } - } - heap[now] = last; - return min; -} - -typedef struct { - pn_list_t *list; - size_t index; -} pni_list_iter_t; - -static void *pni_list_next(void *ctx) -{ - pni_list_iter_t *iter = (pni_list_iter_t *) ctx; - if (iter->index < pn_list_size(iter->list)) { - return pn_list_get(iter->list, iter->index++); - } else { - return NULL; - } -} - -void pn_list_iterator(pn_list_t *list, pn_iterator_t *iter) -{ - pni_list_iter_t *liter = (pni_list_iter_t *) pn_iterator_start(iter, pni_list_next, sizeof(pni_list_iter_t)); - liter->list = list; - liter->index = 0; -} - -static void pn_list_finalize(void *object) -{ - assert(object); - pn_list_t *list = (pn_list_t *) object; - for (size_t i = 0; i < list->size; i++) { - pn_class_decref(list->clazz, pn_list_get(list, i)); - } - free(list->elements); -} - -static uintptr_t pn_list_hashcode(void *object) -{ - assert(object); - pn_list_t *list = (pn_list_t *) object; - uintptr_t hash = 1; - - for (size_t i = 0; i < list->size; i++) { - hash = hash * 31 + pn_hashcode(pn_list_get(list, i)); - } - - return hash; -} - -static intptr_t pn_list_compare(void *oa, void *ob) -{ - assert(oa); assert(ob); - pn_list_t *a = (pn_list_t *) oa; - pn_list_t *b = (pn_list_t *) ob; - - size_t na = pn_list_size(a); - size_t nb = pn_list_size(b); - if (na != nb) { - return nb - na; - } else { - for (size_t i = 0; i < na; i++) { - intptr_t delta = pn_compare(pn_list_get(a, i), pn_list_get(b, i)); - if (delta) return delta; - } - } - - return 0; -} - -static int pn_list_inspect(void *obj, pn_string_t *dst) -{ - assert(obj); - pn_list_t *list = (pn_list_t *) obj; - int err = pn_string_addf(dst, "["); - if (err) return err; - size_t n = pn_list_size(list); - for (size_t i = 0; i < n; i++) { - if (i > 0) { - err = pn_string_addf(dst, ", "); - if (err) return err; - } - err = pn_class_inspect(list->clazz, pn_list_get(list, i), dst); - if (err) return err; - } - return pn_string_addf(dst, "]"); -} - -#define pn_list_initialize NULL - -pn_list_t *pn_list(const pn_class_t *clazz, size_t capacity) -{ - static const pn_class_t list_clazz = PN_CLASS(pn_list); - - pn_list_t *list = (pn_list_t *) pn_class_new(&list_clazz, sizeof(pn_list_t)); - list->clazz = clazz; - list->capacity = capacity ? capacity : 16; - list->elements = (void **) malloc(list->capacity * sizeof(void *)); - list->size = 0; - return list; -} - http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/a5850716/proton-c/src/object/map.c ---------------------------------------------------------------------- diff --git a/proton-c/src/object/map.c b/proton-c/src/object/map.c deleted file mode 100644 index cd38f19..0000000 --- a/proton-c/src/object/map.c +++ /dev/null @@ -1,461 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <proton/object.h> -#include <stdlib.h> -#include <assert.h> - -#define PNI_ENTRY_FREE (0) -#define PNI_ENTRY_LINK (1) -#define PNI_ENTRY_TAIL (2) - -typedef struct { - void *key; - void *value; - size_t next; - uint8_t state; -} pni_entry_t; - -struct pn_map_t { - const pn_class_t *key; - const pn_class_t *value; - pni_entry_t *entries; - size_t capacity; - size_t addressable; - size_t size; - uintptr_t (*hashcode)(void *key); - bool (*equals)(void *a, void *b); - float load_factor; -}; - -static void pn_map_finalize(void *object) -{ - pn_map_t *map = (pn_map_t *) object; - - for (size_t i = 0; i < map->capacity; i++) { - if (map->entries[i].state != PNI_ENTRY_FREE) { - pn_class_decref(map->key, map->entries[i].key); - pn_class_decref(map->value, map->entries[i].value); - } - } - - free(map->entries); -} - -static uintptr_t pn_map_hashcode(void *object) -{ - pn_map_t *map = (pn_map_t *) object; - - uintptr_t hashcode = 0; - - for (size_t i = 0; i < map->capacity; i++) { - if (map->entries[i].state != PNI_ENTRY_FREE) { - void *key = map->entries[i].key; - void *value = map->entries[i].value; - hashcode += pn_hashcode(key) ^ pn_hashcode(value); - } - } - - return hashcode; -} - -static void pni_map_allocate(pn_map_t *map) -{ - map->entries = (pni_entry_t *) malloc(map->capacity * sizeof (pni_entry_t)); - if (map->entries != NULL) { - for (size_t i = 0; i < map->capacity; i++) { - map->entries[i].key = NULL; - map->entries[i].value = NULL; - map->entries[i].next = 0; - map->entries[i].state = PNI_ENTRY_FREE; - } - } - map->size = 0; -} - -static int pn_map_inspect(void *obj, pn_string_t *dst) -{ - assert(obj); - pn_map_t *map = (pn_map_t *) obj; - int err = pn_string_addf(dst, "{"); - if (err) return err; - pn_handle_t entry = pn_map_head(map); - bool first = true; - while (entry) { - if (first) { - first = false; - } else { - err = pn_string_addf(dst, ", "); - if (err) return err; - } - err = pn_class_inspect(map->key, pn_map_key(map, entry), dst); - if (err) return err; - err = pn_string_addf(dst, ": "); - if (err) return err; - err = pn_class_inspect(map->value, pn_map_value(map, entry), dst); - if (err) return err; - entry = pn_map_next(map, entry); - } - return pn_string_addf(dst, "}"); -} - -#define pn_map_initialize NULL -#define pn_map_compare NULL - -pn_map_t *pn_map(const pn_class_t *key, const pn_class_t *value, - size_t capacity, float load_factor) -{ - static const pn_class_t clazz = PN_CLASS(pn_map); - - pn_map_t *map = (pn_map_t *) pn_class_new(&clazz, sizeof(pn_map_t)); - map->key = key; - map->value = value; - map->capacity = capacity ? capacity : 16; - map->addressable = (size_t) (map->capacity * 0.86); - if (!map->addressable) map->addressable = map->capacity; - map->load_factor = load_factor; - map->hashcode = pn_hashcode; - map->equals = pn_equals; - pni_map_allocate(map); - return map; -} - -size_t pn_map_size(pn_map_t *map) -{ - assert(map); - return map->size; -} - -static float pni_map_load(pn_map_t *map) -{ - return ((float) map->size) / ((float) map->addressable); -} - -static bool pni_map_ensure(pn_map_t *map, size_t capacity) -{ - float load = pni_map_load(map); - if (capacity <= map->capacity && load <= map->load_factor) { - return false; - } - - size_t oldcap = map->capacity; - - while (map->capacity < capacity || pni_map_load(map) > map->load_factor) { - map->capacity *= 2; - map->addressable = (size_t) (0.86 * map->capacity); - } - - pni_entry_t *entries = map->entries; - pni_map_allocate(map); - - for (size_t i = 0; i < oldcap; i++) { - if (entries[i].state != PNI_ENTRY_FREE) { - void *key = entries[i].key; - void *value = entries[i].value; - pn_map_put(map, key, value); - } - } - - for (size_t i = 0; i < oldcap; i++) { - if (entries[i].state != PNI_ENTRY_FREE) { - void *key = entries[i].key; - void *value = entries[i].value; - pn_class_decref(map->key, key); - pn_class_decref(map->value, value); - } - } - - free(entries); - return true; -} - -static pni_entry_t *pni_map_entry(pn_map_t *map, void *key, pni_entry_t **pprev, bool create) -{ - uintptr_t hashcode = map->hashcode(key); - - pni_entry_t *entry = &map->entries[hashcode % map->addressable]; - pni_entry_t *prev = NULL; - - if (entry->state == PNI_ENTRY_FREE) { - if (create) { - entry->state = PNI_ENTRY_TAIL; - entry->key = key; - pn_class_incref(map->key, key); - map->size++; - return entry; - } else { - return NULL; - } - } - - while (true) { - if (map->equals(entry->key, key)) { - if (pprev) *pprev = prev; - return entry; - } - - if (entry->state == PNI_ENTRY_TAIL) { - break; - } else { - prev = entry; - entry = &map->entries[entry->next]; - } - } - - if (create) { - if (pni_map_ensure(map, map->size + 1)) { - // if we had to grow the table we need to start over - return pni_map_entry(map, key, pprev, create); - } - - size_t empty = 0; - for (size_t i = 0; i < map->capacity; i++) { - size_t idx = map->capacity - i - 1; - if (map->entries[idx].state == PNI_ENTRY_FREE) { - empty = idx; - break; - } - } - entry->next = empty; - entry->state = PNI_ENTRY_LINK; - map->entries[empty].state = PNI_ENTRY_TAIL; - map->entries[empty].key = key; - pn_class_incref(map->key, key); - if (pprev) *pprev = entry; - map->size++; - return &map->entries[empty]; - } else { - return NULL; - } -} - -int pn_map_put(pn_map_t *map, void *key, void *value) -{ - assert(map); - pni_entry_t *entry = pni_map_entry(map, key, NULL, true); - void *dref_val = entry->value; - entry->value = value; - pn_class_incref(map->value, value); - pn_class_decref(map->value, dref_val); - return 0; -} - -void *pn_map_get(pn_map_t *map, void *key) -{ - assert(map); - pni_entry_t *entry = pni_map_entry(map, key, NULL, false); - return entry ? entry->value : NULL; -} - -static void pni_map_rehash(pn_map_t *map, size_t index) -{ - //reinsert entries in chain starting at index - assert(map); - size_t i = index; - bool complete = false; - while (!complete) { - pni_entry_t *entry = &map->entries[i]; - assert(entry); - assert(entry->state != PNI_ENTRY_FREE); - size_t current = i; - if (entry->state == PNI_ENTRY_TAIL) { - complete = true; - } else { - assert(entry->state == PNI_ENTRY_LINK); - i = entry->next; - } - uintptr_t hashcode = map->hashcode(entry->key); - pni_entry_t *reloc = &map->entries[hashcode % map->addressable]; - if (reloc->state == PNI_ENTRY_FREE) { - //correct addressable slot is available, copy into that... - reloc->state = PNI_ENTRY_TAIL; - reloc->key = entry->key; - reloc->value = entry->value; - //...then free the current entry - entry->key = NULL; - entry->value = NULL; - entry->state = PNI_ENTRY_FREE; - entry->next = 0; - } else { - //iterate to end of chain... - while (reloc->state == PNI_ENTRY_LINK) { - reloc = &map->entries[reloc->next]; - } - assert(reloc->state == PNI_ENTRY_TAIL); - //... and append current entry - reloc->state = PNI_ENTRY_LINK; - reloc->next = current; - entry->state = PNI_ENTRY_TAIL; - entry->next = 0; - } - } -} - -void pn_map_del(pn_map_t *map, void *key) -{ - assert(map); - pni_entry_t *prev = NULL; - pni_entry_t *entry = pni_map_entry(map, key, &prev, false); - if (entry) { - uint8_t orig_state = entry->state; - size_t orig_next = entry->next; - - void *dref_key = entry->key; - void *dref_value = entry->value; - if (prev) { - prev->next = 0; - prev->state = PNI_ENTRY_TAIL; - } - entry->state = PNI_ENTRY_FREE; - entry->next = 0; - entry->key = NULL; - entry->value = NULL; - map->size--; - - if (orig_state == PNI_ENTRY_LINK) { - pni_map_rehash(map, orig_next); - } - - // do this last as it may trigger further deletions - pn_class_decref(map->key, dref_key); - pn_class_decref(map->value, dref_value); - } -} - -pn_handle_t pn_map_head(pn_map_t *map) -{ - assert(map); - for (size_t i = 0; i < map->capacity; i++) - { - if (map->entries[i].state != PNI_ENTRY_FREE) { - return (pn_handle_t)(i + 1); - } - } - - return 0; -} - -pn_handle_t pn_map_next(pn_map_t *map, pn_handle_t entry) -{ - for (size_t i = (size_t)entry; i < map->capacity; i++) { - if (map->entries[i].state != PNI_ENTRY_FREE) { - return (pn_handle_t)(i + 1); - } - } - - return 0; -} - -void *pn_map_key(pn_map_t *map, pn_handle_t entry) -{ - assert(map); - assert(entry); - return map->entries[(size_t)entry - 1].key; -} - -void *pn_map_value(pn_map_t *map, pn_handle_t entry) -{ - assert(map); - assert(entry); - return map->entries[(size_t)entry - 1].value; -} - -struct pn_hash_t { - pn_map_t map; -}; - -static uintptr_t pni_identity_hashcode(void *obj) -{ - return (uintptr_t ) obj; -} - -static bool pni_identity_equals(void *a, void *b) -{ - return a == b; -} - -#define CID_pni_uintptr CID_pn_void -static const pn_class_t *pni_uintptr_reify(void *object); -#define pni_uintptr_new NULL -#define pni_uintptr_free NULL -#define pni_uintptr_initialize NULL -static void pni_uintptr_incref(void *object) {} -static void pni_uintptr_decref(void *object) {} -static int pni_uintptr_refcount(void *object) { return -1; } -#define pni_uintptr_finalize NULL -#define pni_uintptr_hashcode NULL -#define pni_uintptr_compare NULL -#define pni_uintptr_inspect NULL - -static const pn_class_t PN_UINTPTR[] = {PN_METACLASS(pni_uintptr)}; - -static const pn_class_t *pni_uintptr_reify(void *object) -{ - return PN_UINTPTR; -} - -pn_hash_t *pn_hash(const pn_class_t *clazz, size_t capacity, float load_factor) -{ - pn_hash_t *hash = (pn_hash_t *) pn_map(PN_UINTPTR, clazz, capacity, load_factor); - hash->map.hashcode = pni_identity_hashcode; - hash->map.equals = pni_identity_equals; - return hash; -} - -size_t pn_hash_size(pn_hash_t *hash) -{ - return pn_map_size(&hash->map); -} - -int pn_hash_put(pn_hash_t *hash, uintptr_t key, void *value) -{ - return pn_map_put(&hash->map, (void *) key, value); -} - -void *pn_hash_get(pn_hash_t *hash, uintptr_t key) -{ - return pn_map_get(&hash->map, (void *) key); -} - -void pn_hash_del(pn_hash_t *hash, uintptr_t key) -{ - pn_map_del(&hash->map, (void *) key); -} - -pn_handle_t pn_hash_head(pn_hash_t *hash) -{ - return pn_map_head(&hash->map); -} - -pn_handle_t pn_hash_next(pn_hash_t *hash, pn_handle_t entry) -{ - return pn_map_next(&hash->map, entry); -} - -uintptr_t pn_hash_key(pn_hash_t *hash, pn_handle_t entry) -{ - return (uintptr_t) pn_map_key(&hash->map, entry); -} - -void *pn_hash_value(pn_hash_t *hash, pn_handle_t entry) -{ - return pn_map_value(&hash->map, entry); -} --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
