http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/c/src/messenger/store.c ---------------------------------------------------------------------- diff --git a/c/src/messenger/store.c b/c/src/messenger/store.c new file mode 100644 index 0000000..44f24f1 --- /dev/null +++ b/c/src/messenger/store.c @@ -0,0 +1,442 @@ +/* + * + * 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/messenger.h> +#include <proton/engine.h> +#include <proton/object.h> +#include <assert.h> +#ifndef __cplusplus +#include <stdbool.h> +#endif +#include <stdlib.h> +#include <string.h> +#include "core/util.h" +#include "store.h" + +typedef struct pni_stream_t pni_stream_t; + +struct pni_store_t { + pni_stream_t *streams; + pni_entry_t *store_head; + pni_entry_t *store_tail; + pn_hash_t *tracked; + size_t size; + int window; + pn_sequence_t lwm; + pn_sequence_t hwm; +}; + +struct pni_stream_t { + pni_store_t *store; + pn_string_t *address; + pni_entry_t *stream_head; + pni_entry_t *stream_tail; + pni_stream_t *next; +}; + +struct pni_entry_t { + pni_stream_t *stream; + pni_entry_t *stream_next; + pni_entry_t *stream_prev; + pni_entry_t *store_next; + pni_entry_t *store_prev; + pn_buffer_t *bytes; + pn_delivery_t *delivery; + void *context; + pn_status_t status; + pn_sequence_t id; + bool free; +}; + +void pni_entry_finalize(void *object) +{ + pni_entry_t *entry = (pni_entry_t *) object; + assert(entry->free); + pn_delivery_t *d = entry->delivery; + if (d) { + pn_delivery_settle(d); + pni_entry_set_delivery(entry, NULL); + } +} + +pni_store_t *pni_store() +{ + pni_store_t *store = (pni_store_t *) malloc(sizeof(pni_store_t)); + if (!store) return NULL; + + store->size = 0; + store->streams = NULL; + store->store_head = NULL; + store->store_tail = NULL; + store->window = 0; + store->lwm = 0; + store->hwm = 0; + store->tracked = pn_hash(PN_OBJECT, 0, 0.75); + + return store; +} + +size_t pni_store_size(pni_store_t *store) +{ + assert(store); + return store->size; +} + +pni_stream_t *pni_stream(pni_store_t *store, const char *address, bool create) +{ + assert(store); + assert(address); + + pni_stream_t *prev = NULL; + pni_stream_t *stream = store->streams; + while (stream) { + if (!strcmp(pn_string_get(stream->address), address)) { + return stream; + } + prev = stream; + stream = stream->next; + } + + if (create) { + stream = (pni_stream_t *) malloc(sizeof(pni_stream_t)); + if (stream != NULL) { + stream->store = store; + stream->address = pn_string(address); + stream->stream_head = NULL; + stream->stream_tail = NULL; + stream->next = NULL; + + if (prev) { + prev->next = stream; + } else { + store->streams = stream; + } + } + } + + return stream; +} + +pni_stream_t *pni_stream_head(pni_store_t *store) +{ + assert(store); + return store->streams; +} + +pni_stream_t *pni_stream_next(pni_stream_t *stream) +{ + assert(stream); + return stream->next; +} + +void pni_entry_free(pni_entry_t *entry) +{ + if (!entry) return; + pni_stream_t *stream = entry->stream; + pni_store_t *store = stream->store; + LL_REMOVE(stream, stream, entry); + LL_REMOVE(store, store, entry); + entry->free = true; + + pn_buffer_free(entry->bytes); + entry->bytes = NULL; + pn_decref(entry); + store->size--; +} + +void pni_stream_free(pni_stream_t *stream) +{ + if (!stream) return; + pni_entry_t *entry; + while ((entry = LL_HEAD(stream, stream))) { + pni_entry_free(entry); + } + pn_free(stream->address); + stream->address = NULL; + free(stream); +} + +void pni_store_free(pni_store_t *store) +{ + if (!store) return; + pn_free(store->tracked); + pni_stream_t *stream = store->streams; + while (stream) { + pni_stream_t *next = stream->next; + pni_stream_free(stream); + stream = next; + } + free(store); +} + +pni_stream_t *pni_stream_put(pni_store_t *store, const char *address) +{ + assert(store); assert(address); + return pni_stream(store, address, true); +} + +pni_stream_t *pni_stream_get(pni_store_t *store, const char *address) +{ + assert(store); assert(address); + return pni_stream(store, address, false); +} + +#define CID_pni_entry CID_pn_object +#define pni_entry_initialize NULL +#define pni_entry_hashcode NULL +#define pni_entry_compare NULL +#define pni_entry_inspect NULL + +pni_entry_t *pni_store_put(pni_store_t *store, const char *address) +{ + assert(store); + static const pn_class_t clazz = PN_CLASS(pni_entry); + + if (!address) address = ""; + pni_stream_t *stream = pni_stream_put(store, address); + if (!stream) return NULL; + pni_entry_t *entry = (pni_entry_t *) pn_class_new(&clazz, sizeof(pni_entry_t)); + if (!entry) return NULL; + entry->stream = stream; + entry->free = false; + entry->stream_next = NULL; + entry->stream_prev = NULL; + entry->store_next = NULL; + entry->store_prev = NULL; + entry->delivery = NULL; + entry->bytes = pn_buffer(64); + entry->status = PN_STATUS_UNKNOWN; + LL_ADD(stream, stream, entry); + LL_ADD(store, store, entry); + store->size++; + return entry; +} + +pni_entry_t *pni_store_get(pni_store_t *store, const char *address) +{ + assert(store); + if (address) { + pni_stream_t *stream = pni_stream_get(store, address); + if (!stream) return NULL; + return LL_HEAD(stream, stream); + } else { + return LL_HEAD(store, store); + } +} + +pn_buffer_t *pni_entry_bytes(pni_entry_t *entry) +{ + assert(entry); + return entry->bytes; +} + +pn_status_t pni_entry_get_status(pni_entry_t *entry) +{ + assert(entry); + return entry->status; +} + +void pni_entry_set_status(pni_entry_t *entry, pn_status_t status) +{ + assert(entry); + entry->status = status; +} + +pn_delivery_t *pni_entry_get_delivery(pni_entry_t *entry) +{ + assert(entry); + return entry->delivery; +} + +void pni_entry_set_delivery(pni_entry_t *entry, pn_delivery_t *delivery) +{ + assert(entry); + if (entry->delivery) { + pn_delivery_set_context(entry->delivery, NULL); + } + entry->delivery = delivery; + if (delivery) { + pn_delivery_set_context(delivery, entry); + } + pni_entry_updated(entry); +} + +void pni_entry_set_context(pni_entry_t *entry, void *context) +{ + assert(entry); + entry->context = context; +} + +void *pni_entry_get_context(pni_entry_t *entry) +{ + assert(entry); + return entry->context; +} + +static pn_status_t disp2status(uint64_t disp) +{ + if (!disp) return PN_STATUS_PENDING; + + switch (disp) { + case PN_RECEIVED: + return PN_STATUS_PENDING; + case PN_ACCEPTED: + return PN_STATUS_ACCEPTED; + case PN_REJECTED: + return PN_STATUS_REJECTED; + case PN_RELEASED: + return PN_STATUS_RELEASED; + case PN_MODIFIED: + return PN_STATUS_MODIFIED; + default: + assert(0); + } + + return (pn_status_t) 0; +} + + +void pni_entry_updated(pni_entry_t *entry) +{ + assert(entry); + pn_delivery_t *d = entry->delivery; + if (d) { + if (pn_delivery_remote_state(d)) { + entry->status = disp2status(pn_delivery_remote_state(d)); + } else if (pn_delivery_settled(d)) { + uint64_t disp = pn_delivery_local_state(d); + if (disp) { + entry->status = disp2status(disp); + } else { + entry->status = PN_STATUS_SETTLED; + } + } else { + entry->status = PN_STATUS_PENDING; + } + } +} + +pn_sequence_t pni_entry_id(pni_entry_t *entry) +{ + assert(entry); + return entry->id; +} + +pni_entry_t *pni_store_entry(pni_store_t *store, pn_sequence_t id) +{ + assert(store); + return (pni_entry_t *) pn_hash_get(store->tracked, id); +} + +bool pni_store_tracking(pni_store_t *store, pn_sequence_t id) +{ + return (id - store->lwm >= 0) && (store->hwm - id > 0); +} + +pn_sequence_t pni_entry_track(pni_entry_t *entry) +{ + assert(entry); + + pni_store_t *store = entry->stream->store; + entry->id = store->hwm++; + pn_hash_put(store->tracked, entry->id, entry); + + if (store->window >= 0) { + while (store->hwm - store->lwm > store->window) { + pni_entry_t *e = pni_store_entry(store, store->lwm); + if (e) { + pn_hash_del(store->tracked, store->lwm); + } + store->lwm++; + } + } + + return entry->id; +} + +int pni_store_update(pni_store_t *store, pn_sequence_t id, pn_status_t status, + int flags, bool settle, bool match) +{ + assert(store); + + if (!pni_store_tracking(store, id)) { + return 0; + } + + size_t start; + if (PN_CUMULATIVE & flags) { + start = store->lwm; + } else { + start = id; + } + + for (pn_sequence_t i = start; i <= id; i++) { + pni_entry_t *e = pni_store_entry(store, i); + if (e) { + pn_delivery_t *d = e->delivery; + if (d) { + if (!pn_delivery_local_state(d)) { + if (match) { + pn_delivery_update(d, pn_delivery_remote_state(d)); + } else { + switch (status) { + case PN_STATUS_ACCEPTED: + pn_delivery_update(d, PN_ACCEPTED); + break; + case PN_STATUS_REJECTED: + pn_delivery_update(d, PN_REJECTED); + break; + default: + break; + } + } + + pni_entry_updated(e); + } + } + if (settle) { + if (d) { + pn_delivery_settle(d); + } + pn_hash_del(store->tracked, e->id); + } + } + } + + while (store->hwm - store->lwm > 0 && + !pn_hash_get(store->tracked, store->lwm)) { + store->lwm++; + } + + return 0; +} + +int pni_store_get_window(pni_store_t *store) +{ + assert(store); + return store->window; +} + +void pni_store_set_window(pni_store_t *store, int window) +{ + assert(store); + store->window = window; +}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/c/src/messenger/store.h ---------------------------------------------------------------------- diff --git a/c/src/messenger/store.h b/c/src/messenger/store.h new file mode 100644 index 0000000..22bb94e --- /dev/null +++ b/c/src/messenger/store.h @@ -0,0 +1,54 @@ +#ifndef _PROTON_STORE_H +#define _PROTON_STORE_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 "core/buffer.h" + +typedef struct pni_store_t pni_store_t; +typedef struct pni_entry_t pni_entry_t; + +pni_store_t *pni_store(void); +void pni_store_free(pni_store_t *store); +size_t pni_store_size(pni_store_t *store); +pni_entry_t *pni_store_put(pni_store_t *store, const char *address); +pni_entry_t *pni_store_get(pni_store_t *store, const char *address); + +pn_buffer_t *pni_entry_bytes(pni_entry_t *entry); +pn_status_t pni_entry_get_status(pni_entry_t *entry); +void pni_entry_set_status(pni_entry_t *entry, pn_status_t status); +pn_delivery_t *pni_entry_get_delivery(pni_entry_t *entry); +void pni_entry_set_delivery(pni_entry_t *entry, pn_delivery_t *delivery); +void pni_entry_set_context(pni_entry_t *entry, void *context); +void *pni_entry_get_context(pni_entry_t *entry); +void pni_entry_updated(pni_entry_t *entry); +void pni_entry_free(pni_entry_t *entry); + +pn_sequence_t pni_entry_track(pni_entry_t *entry); +pni_entry_t *pni_store_entry(pni_store_t *store, pn_sequence_t id); +int pni_store_update(pni_store_t *store, pn_sequence_t id, pn_status_t status, + int flags, bool settle, bool match); +int pni_store_get_window(pni_store_t *store); +void pni_store_set_window(pni_store_t *store, int window); + + +#endif /* store.h */ http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/c/src/messenger/subscription.c ---------------------------------------------------------------------- diff --git a/c/src/messenger/subscription.c b/c/src/messenger/subscription.c new file mode 100644 index 0000000..c26d40a --- /dev/null +++ b/c/src/messenger/subscription.c @@ -0,0 +1,136 @@ +/* + * + * 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/messenger.h> +#include <proton/object.h> +#include <assert.h> +#include <string.h> + +#include "messenger.h" + +struct pn_subscription_t { + pn_messenger_t *messenger; + pn_string_t *scheme; + pn_string_t *host; + pn_string_t *port; + pn_string_t *address; + void *context; +}; + +void pn_subscription_initialize(void *obj) +{ + pn_subscription_t *sub = (pn_subscription_t *) obj; + sub->messenger = NULL; + sub->scheme = pn_string(NULL); + sub->host = pn_string(NULL); + sub->port = pn_string(NULL); + sub->address = pn_string(NULL); + sub->context = NULL; +} + +void pn_subscription_finalize(void *obj) +{ + pn_subscription_t *sub = (pn_subscription_t *) obj; + pn_free(sub->scheme); + pn_free(sub->host); + pn_free(sub->port); + pn_free(sub->address); +} + +#define CID_pn_subscription CID_pn_object +#define pn_subscription_hashcode NULL +#define pn_subscription_compare NULL +#define pn_subscription_inspect NULL + +pn_subscription_t *pn_subscription(pn_messenger_t *messenger, + const char *scheme, + const char *host, + const char *port) +{ + static const pn_class_t clazz = PN_CLASS(pn_subscription); + pn_subscription_t *sub = (pn_subscription_t *) pn_class_new(&clazz, sizeof(pn_subscription_t)); + sub->messenger = messenger; + pn_string_set(sub->scheme, scheme); + pn_string_set(sub->host, host); + pn_string_set(sub->port, port); + pni_messenger_add_subscription(messenger, sub); + pn_class_decref(PN_OBJECT, sub); + return sub; +} + +const char *pn_subscription_scheme(pn_subscription_t *sub) +{ + assert(sub); + return pn_string_get(sub->scheme); +} + +void *pn_subscription_get_context(pn_subscription_t *sub) +{ + assert(sub); + return sub->context; +} + +void pn_subscription_set_context(pn_subscription_t *sub, void *context) +{ + assert(sub); + sub->context = context; +} + +int pni_subscription_set_address(pn_subscription_t *sub, const char *address) +{ + assert(sub); + + if (!address) return 0; + + bool absolute = strncmp(address, "amqp:", 5) == 0; + + if (absolute) { + return pn_string_set(sub->address, address); + } else { + pn_string_set(sub->address, ""); + bool scheme = pn_string_get(sub->scheme); + if (scheme) { + int e = pn_string_addf(sub->address, "%s:", pn_string_get(sub->scheme)); + if (e) return e; + } + if (pn_string_get(sub->host)) { + int e = pn_string_addf(sub->address, scheme ? "//%s" : "%s", pn_string_get(sub->host)); + if (e) return e; + } + if (pn_string_get(sub->port)) { + int e = pn_string_addf(sub->address, ":%s", pn_string_get(sub->port)); + if (e) return e; + } + return pn_string_addf(sub->address, "/%s", address); + } +} + +const char *pn_subscription_address(pn_subscription_t *sub) +{ + assert(sub); + while (!pn_string_get(sub->address)) { + int err = pni_messenger_work(sub->messenger); + if (err < 0) { + return NULL; + } + } + return pn_string_get(sub->address); +} http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/c/src/messenger/subscription.h ---------------------------------------------------------------------- diff --git a/c/src/messenger/subscription.h b/c/src/messenger/subscription.h new file mode 100644 index 0000000..a390eb5 --- /dev/null +++ b/c/src/messenger/subscription.h @@ -0,0 +1,33 @@ +#ifndef _PROTON_SUBSCRIPTION_H +#define _PROTON_SUBSCRIPTION_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/messenger.h> + +pn_subscription_t *pn_subscription(pn_messenger_t *messenger, + const char *scheme, const char *host, + const char *port); +const char *pn_subscription_scheme(pn_subscription_t *sub); +int pni_subscription_set_address(pn_subscription_t *sub, const char *address); + +#endif /* subscription.h */ http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/c/src/messenger/transform.c ---------------------------------------------------------------------- diff --git a/c/src/messenger/transform.c b/c/src/messenger/transform.c new file mode 100644 index 0000000..9b726f8 --- /dev/null +++ b/c/src/messenger/transform.c @@ -0,0 +1,255 @@ +/* + * + * 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 <string.h> +#include <assert.h> +#include <ctype.h> +#include "transform.h" + +typedef struct { + const char *start; + size_t size; +} pn_group_t; + +#define MAX_GROUP (64) + +typedef struct { + size_t groups; + pn_group_t group[MAX_GROUP]; +} pn_matcher_t; + +typedef struct { + pn_string_t *pattern; + pn_string_t *substitution; +} pn_rule_t; + +struct pn_transform_t { + pn_list_t *rules; + pn_matcher_t matcher; + bool matched; +}; + +static void pn_rule_finalize(void *object) +{ + pn_rule_t *rule = (pn_rule_t *) object; + pn_free(rule->pattern); + pn_free(rule->substitution); +} + +#define CID_pn_rule CID_pn_object +#define pn_rule_initialize NULL +#define pn_rule_hashcode NULL +#define pn_rule_compare NULL +#define pn_rule_inspect NULL + +pn_rule_t *pn_rule(const char *pattern, const char *substitution) +{ + static const pn_class_t clazz = PN_CLASS(pn_rule); + pn_rule_t *rule = (pn_rule_t *) pn_class_new(&clazz, sizeof(pn_rule_t)); + rule->pattern = pn_string(pattern); + rule->substitution = pn_string(substitution); + return rule; +} + +static void pn_transform_finalize(void *object) +{ + pn_transform_t *transform = (pn_transform_t *) object; + pn_free(transform->rules); +} + +#define CID_pn_transform CID_pn_object +#define pn_transform_initialize NULL +#define pn_transform_hashcode NULL +#define pn_transform_compare NULL +#define pn_transform_inspect NULL + +pn_transform_t *pn_transform() +{ + static const pn_class_t clazz = PN_CLASS(pn_transform); + pn_transform_t *transform = (pn_transform_t *) pn_class_new(&clazz, sizeof(pn_transform_t)); + transform->rules = pn_list(PN_OBJECT, 0); + transform->matched = false; + return transform; +} + +void pn_transform_rule(pn_transform_t *transform, const char *pattern, + const char *substitution) +{ + assert(transform); + pn_rule_t *rule = pn_rule(pattern, substitution); + pn_list_add(transform->rules, rule); + pn_decref(rule); +} + +static void pni_sub(pn_matcher_t *matcher, size_t group, const char *text, size_t matched) +{ + if (group > matcher->groups) { + matcher->groups = group; + } + matcher->group[group].start = text - matched; + matcher->group[group].size = matched; +} + +static bool pni_match_r(pn_matcher_t *matcher, const char *pattern, const char *text, size_t group, size_t matched) +{ + bool match; + + char p = *pattern; + char c = *text; + + switch (p) { + case '\0': return c == '\0'; + case '%': + case '*': + switch (c) { + case '\0': + match = pni_match_r(matcher, pattern + 1, text, group + 1, 0); + if (match) pni_sub(matcher, group, text, matched); + return match; + case '/': + if (p == '%') { + match = pni_match_r(matcher, pattern + 1, text, group + 1, 0); + if (match) pni_sub(matcher, group, text, matched); + return match; + } + // Fallthrough + default: + match = pni_match_r(matcher, pattern, text + 1, group, matched + 1); + if (!match) { + match = pni_match_r(matcher, pattern + 1, text, group + 1, 0); + if (match) pni_sub(matcher, group, text, matched); + } + return match; + } + default: + return c == p && pni_match_r(matcher, pattern + 1, text + 1, group, 0); + } +} + +static bool pni_match(pn_matcher_t *matcher, const char *pattern, const char *text) +{ + text = text ? text : ""; + matcher->groups = 0; + if (pni_match_r(matcher, pattern, text, 1, 0)) { + matcher->group[0].start = text; + matcher->group[0].size = strlen(text); + return true; + } else { + matcher->groups = 0; + return false; + } +} + +static size_t pni_substitute(pn_matcher_t *matcher, const char *pattern, char *dest, size_t limit) +{ + size_t result = 0; + + while (*pattern) { + switch (*pattern) { + case '$': + pattern++; + if (*pattern == '$') { + if (result < limit) { + *dest++ = *pattern; + } + pattern++; + result++; + } else { + size_t idx = 0; + while (isdigit(*pattern)) { + idx *= 10; + idx += *pattern++ - '0'; + } + + if (idx <= matcher->groups) { + pn_group_t *group = &matcher->group[idx]; + for (size_t i = 0; i < group->size; i++) { + if (result < limit) { + *dest++ = group->start[i]; + } + result++; + } + } + } + break; + default: + if (result < limit) { + *dest++ = *pattern; + } + pattern++; + result++; + break; + } + } + + if (result < limit) { + *dest = '\0'; + } + + return result; +} + +int pn_transform_apply(pn_transform_t *transform, const char *src, + pn_string_t *dst) +{ + for (size_t i = 0; i < pn_list_size(transform->rules); i++) + { + pn_rule_t *rule = (pn_rule_t *) pn_list_get(transform->rules, i); + if (pni_match(&transform->matcher, pn_string_get(rule->pattern), src)) { + transform->matched = true; + if (!pn_string_get(rule->substitution)) { + return pn_string_set(dst, NULL); + } + + while (true) { + size_t capacity = pn_string_capacity(dst); + size_t n = pni_substitute(&transform->matcher, + pn_string_get(rule->substitution), + pn_string_buffer(dst), capacity); + int err = pn_string_resize(dst, n); + if (err) return err; + if (n <= capacity) { + return 0; + } + } + } + } + + transform->matched = false; + return pn_string_set(dst, src); +} + +bool pn_transform_matched(pn_transform_t *transform) +{ + return transform->matched; +} + +int pn_transform_get_substitutions(pn_transform_t *transform, + pn_list_t *substitutions) +{ + int size = pn_list_size(transform->rules); + for (size_t i = 0; i < (size_t)size; i++) { + pn_rule_t *rule = (pn_rule_t *)pn_list_get(transform->rules, i); + pn_list_add(substitutions, rule->substitution); + } + + return size; +} http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/c/src/messenger/transform.h ---------------------------------------------------------------------- diff --git a/c/src/messenger/transform.h b/c/src/messenger/transform.h new file mode 100644 index 0000000..3288f6c --- /dev/null +++ b/c/src/messenger/transform.h @@ -0,0 +1,40 @@ +#ifndef _PROTON_TRANSFORM_H +#define _PROTON_TRANSFORM_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 "core/buffer.h" + +#include <proton/object.h> + +typedef struct pn_transform_t pn_transform_t; + +pn_transform_t *pn_transform(void); +void pn_transform_rule(pn_transform_t *transform, const char *pattern, + const char *substitution); +int pn_transform_apply(pn_transform_t *transform, const char *src, + pn_string_t *dest); +bool pn_transform_matched(pn_transform_t *transform); +int pn_transform_get_substitutions(pn_transform_t *transform, + pn_list_t *substitutions); + +#endif /* transform.h */ http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/c/src/platform/platform.c ---------------------------------------------------------------------- diff --git a/c/src/platform/platform.c b/c/src/platform/platform.c new file mode 100644 index 0000000..393f75c --- /dev/null +++ b/c/src/platform/platform.c @@ -0,0 +1,122 @@ +/* + * + * 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 "platform.h" + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> + +#ifdef PN_WINAPI +#include <windows.h> +int pn_i_getpid() { + return (int) GetCurrentProcessId(); +} +#else +#include <unistd.h> +int pn_i_getpid() { + return (int) getpid(); +} +#endif + +void pni_vfatal(const char *fmt, va_list ap) +{ + vfprintf(stderr, fmt, ap); + abort(); +} + +void pni_fatal(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + pni_vfatal(fmt, ap); + va_end(ap); +} + +/* Allow for systems that do not implement clock_gettime()*/ +#ifdef USE_CLOCK_GETTIME +#include <time.h> +pn_timestamp_t pn_i_now(void) +{ + struct timespec now; + if (clock_gettime(CLOCK_REALTIME, &now)) pni_fatal("clock_gettime() failed\n"); + return ((pn_timestamp_t)now.tv_sec) * 1000 + (now.tv_nsec / 1000000); +} +#elif defined(USE_WIN_FILETIME) +#include <windows.h> +pn_timestamp_t pn_i_now(void) +{ + FILETIME now; + GetSystemTimeAsFileTime(&now); + ULARGE_INTEGER t; + t.u.HighPart = now.dwHighDateTime; + t.u.LowPart = now.dwLowDateTime; + // Convert to milliseconds and adjust base epoch + return t.QuadPart / 10000 - 11644473600000; +} +#else +#include <sys/time.h> +pn_timestamp_t pn_i_now(void) +{ + struct timeval now; + if (gettimeofday(&now, NULL)) pni_fatal("gettimeofday failed\n"); + return ((pn_timestamp_t)now.tv_sec) * 1000 + (now.tv_usec / 1000); +} +#endif + +#include <string.h> +#include <stdio.h> +static void pn_i_strerror(int errnum, char *buf, size_t buflen) +{ + // PROTON-1029 provide a simple default in case strerror fails + pni_snprintf(buf, buflen, "errno: %d", errnum); +#ifdef USE_STRERROR_R + strerror_r(errnum, buf, buflen); +#elif USE_STRERROR_S + strerror_s(buf, buflen, errnum); +#elif USE_OLD_STRERROR + strncpy(buf, strerror(errnum), buflen); +#endif +} + +int pn_i_error_from_errno(pn_error_t *error, const char *msg) +{ + char err[1024]; + pn_i_strerror(errno, err, 1024); + int code = PN_ERR; + if (errno == EINTR) + code = PN_INTR; + return pn_error_format(error, code, "%s: %s", msg, err); +} + +#ifdef USE_ATOLL +#include <stdlib.h> +int64_t pn_i_atoll(const char* num) { + return atoll(num); +} +#elif USE_ATOI64 +#include <stdlib.h> +int64_t pn_i_atoll(const char* num) { + return _atoi64(num); +} +#else +#error "Don't know how to convert int64_t values on this platform" +#endif http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/c/src/platform/platform.h ---------------------------------------------------------------------- diff --git a/c/src/platform/platform.h b/c/src/platform/platform.h new file mode 100644 index 0000000..c993bb9 --- /dev/null +++ b/c/src/platform/platform.h @@ -0,0 +1,90 @@ +#ifndef PROTON_PLATFORM_H +#define PROTON_PLATFORM_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/types.h" +#include "proton/error.h" + +/** Get the current PID + * + * @return process id + * @internal + */ +int pn_i_getpid(void); + + +/** Get the current time in pn_timestamp_t format. + * + * Returns current time in milliseconds since Unix Epoch, + * as defined by AMQP 1.0 + * + * @return current time + * @internal + */ +pn_timestamp_t pn_i_now(void); + +/** Generate system error message. + * + * Populate the proton error structure based on the last system error + * code. + * + * @param[in] error the proton error structure + * @param[in] msg the descriptive context message + * @return error->code + * + * @internal + */ +int pn_i_error_from_errno(pn_error_t *error, const char *msg); + +/** Provide C99 atoll functinality. + * + * @param[in] num the string representation of the number. + * @return the integer value. + * + * @internal + */ +int64_t pn_i_atoll(const char* num); + +int pni_snprintf(char *buf, size_t count, const char *fmt, ...); +int pni_vsnprintf(char *buf, size_t count, const char *fmt, va_list ap); + +#ifndef _MSC_VER + +#define pni_snprintf snprintf +#define pni_vsnprintf vsnprintf + +#else + +#if !defined(S_ISDIR) +# define S_ISDIR(X) ((X) & _S_IFDIR) +#endif + +#endif + +#if defined _MSC_VER || defined _OPENVMS +#if !defined(va_copy) +#define va_copy(d,s) ((d) = (s)) +#endif +#endif + +#endif /* platform.h */ http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/c/src/platform/platform_fmt.h ---------------------------------------------------------------------- diff --git a/c/src/platform/platform_fmt.h b/c/src/platform/platform_fmt.h new file mode 100644 index 0000000..17f95f3 --- /dev/null +++ b/c/src/platform/platform_fmt.h @@ -0,0 +1,85 @@ +#ifndef _PROTON_SRC_PLATFORM_FMT_H +#define _PROTON_SRC_PLATFORM_FMT_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. + * + */ + +/* + * Platform dependent type-specific format specifiers for PRIx and %z + * for use with printf. PRIx defs are normally available in + * inttypes.h (C99), but extra steps are required for C++, and they + * are not available in Visual Studio at all. + * Visual studio uses "%I" for size_t instead of "%z". + */ + +#ifndef __cplusplus + +// normal case +#include <inttypes.h> +#define PN_ZI "zi" +#define PN_ZU "zu" + +#ifdef _OPENVMS + +#undef PN_ZI +#undef PN_ZU +#define PN_ZI "i" +#define PN_ZU "u" +#define PRIu64 "llu" +#define PRIu8 "u" +#define PRIu16 "u" +#define PRIu32 "u" +#define PRIu64 "llu" + +#define PRIi8 "i" +#define PRIi16 "i" +#define PRIi32 "i" +#define PRIi64 "lli" + +#endif /* _OPENVMS */ + +#else + +#ifdef _MSC_VER +#define PRIu8 "u" +#define PRIu16 "u" +#define PRIu32 "u" +#define PRIu64 "I64u" + +#define PRIi8 "i" +#define PRIi16 "i" +#define PRIi32 "i" +#define PRIi64 "I64i" + +#define PN_ZI "Ii" +#define PN_ZU "Iu" +#else +// Normal C++ +#define __STDC_FORMAT_MACROS +#include <inttypes.h> +#define PN_ZI "zi" +#define PN_ZU "zu" + +#endif /* _MSC_VER */ + +#endif /* __cplusplus */ + +#endif /* platform_fmt.h */ --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@qpid.apache.org For additional commands, e-mail: commits-h...@qpid.apache.org