You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by jr...@apache.org on 2018/04/05 19:34:10 UTC
[35/51] [partial] qpid-proton git commit: PROTON-1728: Reorganize the
source tree
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-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org