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