HTRACE-386. htrace-c: add functions for retrieving the span ID to the public API. (Colin Patrick McCabe via iwasakims)
diff --git a/htrace-c/src/core/htrace.h b/htrace-c/src/core/htrace.h
index 03c02bb..7357d4c 100644
--- a/htrace-c/src/core/htrace.h
+++ b/htrace-c/src/core/htrace.h
@@ -20,6 +20,7 @@
 #define APACHE_HTRACE_HTRACE_H
 
 #include <stdint.h> /* for uint64_t, etc. */
+#include <unistd.h> /* for size_t, etc. */
 
 /**
  * The public API for the HTrace C client.
@@ -169,6 +170,11 @@
  */
 #define HTRACE_PROB_SAMPLER_FRACTION_KEY "prob.sampler.fraction"
 
+/**
+ * The length of an HTrace span ID in hexadecimal string form.
+ */
+#define HTRACE_SPAN_ID_STRING_LENGTH 32
+
     // Forward declarations
     struct htrace_conf;
     struct htracer;
@@ -342,6 +348,83 @@
      */
     void htrace_scope_close(struct htrace_scope *scope);
 
+    /**
+     * The HTrace span id.
+     */
+    struct htrace_span_id {
+        uint64_t high;
+        uint64_t low;
+    };
+
+    /**
+     * Set a span ID to the invalid span ID by clearing it.
+     *
+     * @param id            The span ID to clear.
+     */
+    void htrace_span_id_clear(struct htrace_span_id *id);
+
+    /**
+     * Compare two span IDs.
+     *
+     * @param a             The first span ID.
+     * @param b             The second span ID.
+     *
+     * @return              A number less than 0 if the first span ID is less;
+     *                      A number greater than 0 if the first span ID is greater;
+     *                      0 if the span IDs are equal.
+     */
+    int htrace_span_id_compare(const struct htrace_span_id *a,
+                               const struct htrace_span_id *b);
+
+    /**
+     * Parse a string containing an HTrace span ID.
+     *
+     * @param id            The HTrace span ID to fill in.
+     * @param str           The string to parse.
+     * @param err           (out parameter) a buffer into which we will
+     *                      write an error message, if parsing fails.
+     *                      If this is unchanged, there was no error.
+     * @param err_len       The length of the err buffer.
+     *
+     */
+    void htrace_span_id_parse(struct htrace_span_id *id, const char *str,
+                             char *err, size_t err_len);
+
+    /**
+     * Write an HTrace span ID to a string.
+     *
+     * @param id            The HTrace span ID.
+     * @param str           Where to put the string.
+     * @param len           The length of the string buffer.
+     *
+     * @return              1 on success; 0 if the length was not long enough, or
+     *                          there was an internal snprintf error.
+     */
+    int htrace_span_id_to_str(const struct htrace_span_id *id,
+                              char *str, size_t len);
+
+    /**
+     * Copy an htrace span ID.
+     *
+     * dst and src can be the same.
+     *
+     * @param dst           The destination span ID.
+     * @param src           The source span ID.
+     */
+    void htrace_span_id_copy(struct htrace_span_id *dst,
+                             const struct htrace_span_id *src);
+
+    /**
+     * Get the span id of an HTrace scope.
+     *
+     * @param scope     The trace scope, or NULL.
+     * @param id        (out param) The htrace span ID object to modify.
+     *                      It will be set to the invalid span ID if the scope
+     *                      is null or has no span.
+     */
+    void htrace_scope_get_span_id(const struct htrace_scope *scope,
+                                  struct htrace_span_id *id);
+
 #pragma GCC visibility pop // End publicly visible symbols
 
 #ifdef __cplusplus
diff --git a/htrace-c/src/core/htrace.hpp b/htrace-c/src/core/htrace.hpp
index 0378c57..6f6a398 100644
--- a/htrace-c/src/core/htrace.hpp
+++ b/htrace-c/src/core/htrace.hpp
@@ -49,6 +49,109 @@
   class Scope;
   class Tracer;
 
+  class SpanId {
+  public:
+    SpanId() {
+      id_.low = 0;
+      id_.high = 0;
+    }
+
+    SpanId(uint64_t high, uint64_t low) {
+      id_.high = high;
+      id_.low = low;
+    }
+
+    SpanId(const struct htrace_span_id *other) {
+      id_.high = other->high;
+      id_.low = other->low;
+    }
+
+    SpanId(const SpanId &other) {
+      id_.high = other.id_.high;
+      id_.low = other.id_.low;
+    }
+
+    /**
+     * Convert an input string into a span id.
+     *
+     * @param input             The input string.
+     *
+     * @return                  The empty string, if parsing was successful.  A
+     *                          failure error message, if parsing failed.
+     *                          If parsing is successful the current ID object
+     *                          will be modified.
+     */
+    std::string FromString(const std::string &input) {
+      char err[512];
+      err[0] = '\0';
+      htrace_span_id_parse(&id_, input.c_str(), err, sizeof(err));
+      if (err[0]) {
+        return std::string(err);
+      }
+      return "";
+    }
+
+    SpanId &operator=(const SpanId &other) {
+      id_.high = other.id_.high;
+      id_.low = other.id_.low;
+      return *this;
+    }
+
+    bool operator<(const SpanId &other) const {
+      return (htrace_span_id_compare(&id_, &other.id_) < 0);
+    }
+
+    bool operator==(const SpanId &other) const {
+      return ((id_.high == other.id_.high) &&
+          (id_.low == other.id_.low));
+    }
+
+    bool operator!=(const SpanId &other) const {
+      return (!((*this) == other));
+    }
+
+    uint64_t GetHigh() {
+      return id_.high;
+    }
+
+    void SetHigh(uint64_t high) {
+      id_.high = high;
+    }
+
+    uint64_t GetLow() {
+      return id_.low;
+    }
+
+    void SetLow(uint64_t low) {
+      id_.low = low;
+    }
+
+    void Clear() {
+      htrace_span_id_clear(&id_);
+    }
+
+    /**
+     * Convert the SpanId to a human-readable string.
+     */
+    std::string ToString() const {
+      char str[HTRACE_SPAN_ID_STRING_LENGTH + 1];
+      if (!htrace_span_id_to_str(&id_, str, sizeof(str))) {
+        // This should not happen, because the buffer we supplied is long
+        // enough.
+        return "(error converting ID to string)";
+      }
+      return std::string(str);
+    }
+
+  private:
+    struct htrace_span_id id_;
+  };
+
+  std::ostream &operator<<(std::ostream &oss, const SpanId &spanId) {
+    oss << spanId.ToString();
+    return oss;
+  }
+
   /**
    * An HTrace Configuration object.
    *
@@ -221,6 +324,12 @@
       scope_ = NULL;
     }
 
+    SpanId GetSpanId() const {
+      htrace_span_id id;
+      htrace_scope_get_span_id(scope_, &id);
+      return SpanId(&id);
+    }
+
   private:
     friend class Tracer;
     Scope(htrace::Scope &other); // Can't copy
diff --git a/htrace-c/src/core/scope.h b/htrace-c/src/core/scope.h
index 9f00b13..6d914b7 100644
--- a/htrace-c/src/core/scope.h
+++ b/htrace-c/src/core/scope.h
@@ -55,17 +55,6 @@
     struct htrace_span *span;
 };
 
-/**
- * Get the span id of an HTrace scope.
- *
- * @param scope     The trace scope, or NULL.
- * @param id        (out param) The htrace span ID object to modify.
- *                      It will be set to the invalid span ID if the scope
- *                      is null or has no span.
- */
-void htrace_scope_get_span_id(const struct htrace_scope *scope,
-                              struct htrace_span_id *id);
-
 #endif
 
 // vim: ts=4:sw=4:et
diff --git a/htrace-c/src/core/span.c b/htrace-c/src/core/span.c
index 44f4e6c..b7ca87a 100644
--- a/htrace-c/src/core/span.c
+++ b/htrace-c/src/core/span.c
@@ -16,6 +16,7 @@
  * limitations under the License.
  */
 
+#include "core/htrace.h"
 #include "core/span.h"
 #include "receiver/receiver.h"
 #include "sampler/sampler.h"
diff --git a/htrace-c/src/core/span.h b/htrace-c/src/core/span.h
index d6fbeb5..b3a79a0 100644
--- a/htrace-c/src/core/span.h
+++ b/htrace-c/src/core/span.h
@@ -27,6 +27,7 @@
  * This is an internal header, not intended for external use.
  */
 
+#include "core/htrace.h" /* for struct span_id */
 #include "core/span_id.h"
 
 #include <stdint.h>
diff --git a/htrace-c/src/core/span_id.c b/htrace-c/src/core/span_id.c
index 7ea23eb..9c4acae 100644
--- a/htrace-c/src/core/span_id.c
+++ b/htrace-c/src/core/span_id.c
@@ -16,6 +16,7 @@
  * limitations under the License.
  */
 
+#include "core/htrace.h"
 #include "core/span_id.h"
 #include "util/cmp.h"
 #include "util/log.h"
diff --git a/htrace-c/src/core/span_id.h b/htrace-c/src/core/span_id.h
index af2e725..8f21bda 100644
--- a/htrace-c/src/core/span_id.h
+++ b/htrace-c/src/core/span_id.h
@@ -34,11 +34,6 @@
 struct random_src;
 
 /**
- * Length of an HTrace span ID in hexadecimal string form.
- */
-#define HTRACE_SPAN_ID_STRING_LENGTH 32
-
-/**
  * The number of bytes in the HTrace span ID
  */
 #define HTRACE_SPAN_ID_NUM_BYTES 16
@@ -49,50 +44,6 @@
 extern const struct htrace_span_id INVALID_SPAN_ID;
 
 /**
- * The HTrace span id.
- */
-struct htrace_span_id {
-    uint64_t high;
-    uint64_t low;
-};
-
-/**
- * Parse a string containing an HTrace span ID.
- *
- * @param id            The HTrace span ID to fill in.
- * @param str           The string to parse.
- *
- */
-void htrace_span_id_parse(struct htrace_span_id *id, const char *str,
-                         char *err, size_t err_len);
-
-/**
- * Write an HTrace span ID to a string.
- *
- * @param id            The HTrace span ID.
- * @param str           Where to put the string.
- * @param len           The length of the string buffer.
- * @param err           The error buffer to be set on failure.
- * @param err_len       Length of the error buffer.
- *
- * @return              1 on success; 0 if the length was not long enough, or
- *                          there was an internal snprintf error.
- */
-int htrace_span_id_to_str(const struct htrace_span_id *id,
-                          char *str, size_t len);
-
-/**
- * Copy an htrace span ID.
- *
- * dst and src can be the same.
- *
- * @param dst           The destination span ID.
- * @param src           The source span ID.
- */
-void htrace_span_id_copy(struct htrace_span_id *dst,
-                         const struct htrace_span_id *src);
-
-/**
  * Write this span ID to the provided CMP context.
  *
  * @param span          The span.
@@ -124,26 +75,6 @@
 void htrace_span_id_generate(struct htrace_span_id *id, struct random_src *rnd,
                              const struct htrace_span_id *parent);
 
-/**
- * Set a span ID to the invalid span ID by clearing it.
- *
- * @param id            The span ID to clear.
- */
-void htrace_span_id_clear(struct htrace_span_id *id);
-
-/**
- * Compare two span IDs.
- *
- * @param a             The first span ID.
- * @param b             The second span ID.
- *
- * @return              A number less than 0 if the first span ID is less;
- *                      A number greater than 0 if the first span ID is greater;
- *                      0 if the span IDs are equal.
- */
-int htrace_span_id_compare(const struct htrace_span_id *a,
-                           const struct htrace_span_id *b);
-
 #endif
 
 // vim: ts=4:sw=4:et
diff --git a/htrace-c/src/test/linkage-unit.c b/htrace-c/src/test/linkage-unit.c
index bba73e1..f3e4caf 100644
--- a/htrace-c/src/test/linkage-unit.c
+++ b/htrace-c/src/test/linkage-unit.c
@@ -48,7 +48,13 @@
     "htrace_start_span",
     "htracer_create",
     "htracer_free",
-    "htracer_tname"
+    "htracer_tname",
+    "htrace_span_id_clear",
+    "htrace_span_id_compare",
+    "htrace_span_id_parse",
+    "htrace_span_id_to_str",
+    "htrace_span_id_copy",
+    "htrace_scope_get_span_id",
 };
 
 #define PUBLIC_SYMS_SIZE (sizeof(PUBLIC_SYMS) / sizeof(PUBLIC_SYMS[0]))
diff --git a/htrace-c/src/test/span_id-unit.c b/htrace-c/src/test/span_id-unit.c
index 06c0320..ecdebfb 100644
--- a/htrace-c/src/test/span_id-unit.c
+++ b/htrace-c/src/test/span_id-unit.c
@@ -16,6 +16,7 @@
  * limitations under the License.
  */
 
+#include "core/htrace.h"
 #include "core/span_id.h"
 #include "test/span_util.h"
 #include "test/test.h"