]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
dwarflint: C++ify coverage analysis
authorPetr Machata <pmachata@redhat.com>
Mon, 5 Oct 2009 19:34:45 +0000 (21:34 +0200)
committerPetr Machata <pmachata@redhat.com>
Wed, 18 Aug 2010 12:55:10 +0000 (14:55 +0200)
* only the implementation so far, we need the interface intact until
  dwarflint low-level is in C

src/dwarflint-coverage.cc [moved from src/dwarflint-coverage.c with 83% similarity]
src/dwarflint-coverage.h
src/dwarflint-coverage.hh [new file with mode: 0644]

similarity index 83%
rename from src/dwarflint-coverage.c
rename to src/dwarflint-coverage.cc
index 1bec5549add1e9ffc5a67161caa2b86f3a866052..aa9b17c3f133e31a0ce78eca01653dc4214b4228 100644 (file)
@@ -1,4 +1,4 @@
-/* Coverage analysis.
+/* Implementation of coverage analysis.
 
    Copyright (C) 2008,2009 Red Hat, Inc.
    This file is part of Red Hat elfutils.
 # include <config.h>
 #endif
 
-#include "dwarflint-coverage.h"
+#include "dwarflint-coverage.hh"
+extern "C"
+{
+#include "../lib/system.h"
+}
+
 #include <stdbool.h>
 #include <assert.h>
-#include <system.h>
 #include <string.h>
 #include <inttypes.h>
 
-static size_t
-coverage_find (struct coverage const *cov, uint64_t start)
+
+namespace
 {
-  assert (cov->size > 0);
+  template <class X>
+  decltype (((X *)0)->ranges)
+  coverage_find (X *cov, uint64_t start)
+  {
+    assert (cov->size > 0);
 
-  size_t a = 0;
-  size_t b = cov->size;
+    size_t a = 0;
+    size_t b = cov->size;
 
-  while (a < b)
-    {
-      size_t i = (a + b) / 2;
-      struct cov_range const *r = cov->ranges + i;
+    while (a < b)
+      {
+       size_t i = (a + b) / 2;
+       cov_range const *r = cov->ranges + i;
 
-      if (r->start > start)
-       b = i;
-      else if (r->start < start)
-       a = i + 1;
-      else
-       return i;
-    }
+       if (r->start > start)
+         b = i;
+       else if (r->start < start)
+         a = i + 1;
+       else
+         return cov->ranges + i;
+      }
 
-  return a;
+    return cov->ranges + a;
+  }
 }
 
 void
@@ -73,7 +82,7 @@ coverage_add (struct coverage *cov, uint64_t start, uint64_t length)
       return;
     }
 
-  struct cov_range *r = cov->ranges + coverage_find (cov, start);
+  struct cov_range *r = coverage_find (cov, start);
 
   struct cov_range *insert = &nr;
   struct cov_range *coalesce = &nr;
@@ -142,7 +151,7 @@ coverage_remove (struct coverage *cov, uint64_t begin, uint64_t length)
   if (cov->size == 0 || begin == end)
     return false;
 
-  struct cov_range *r = cov->ranges + coverage_find (cov, begin);
+  struct cov_range *r = coverage_find (cov, begin);
   struct cov_range *erase_begin = NULL, *erase_end = r; // end exclusive
   bool overlap = false;
 
@@ -214,7 +223,7 @@ coverage_is_covered (struct coverage const *cov,
   if (cov->size == 0)
     return false;
 
-  struct cov_range const *r = cov->ranges + coverage_find (cov, start);
+  struct cov_range const *r = coverage_find (cov, start);
   uint64_t end = start + length;
   if (r < cov->ranges + cov->size)
     if (start >= r->start)
@@ -229,6 +238,17 @@ coverage_is_covered (struct coverage const *cov,
   return false;
 }
 
+namespace
+{
+  bool overlaps (uint64_t start, uint64_t end,
+                struct cov_range const *r)
+  {
+    return (start >= r->start && start < r->start + r->length)
+      || (end > r->start && end <= r->start + r->length)
+      || (start < r->start && end > r->start + r->length);
+  }
+}
+
 bool
 coverage_is_overlap (struct coverage const *cov,
                     uint64_t start, uint64_t length)
@@ -237,20 +257,14 @@ coverage_is_overlap (struct coverage const *cov,
     return false;
 
   uint64_t end = start + length;
-  bool overlaps (struct cov_range const *r)
-  {
-    return (start >= r->start && start < r->start + r->length)
-      || (end > r->start && end <= r->start + r->length)
-      || (start < r->start && end > r->start + r->length);
-  }
 
-  struct cov_range const *r = cov->ranges + coverage_find (cov, start);
+  struct cov_range const *r = coverage_find (cov, start);
 
-  if (r < cov->ranges + cov->size && overlaps (r))
+  if (r < cov->ranges + cov->size && overlaps (start, end, r))
     return true;
 
   if (r > cov->ranges)
-    return overlaps (r - 1);
+    return overlaps (start, end, r - 1);
 
   return false;
 }
@@ -267,25 +281,20 @@ coverage_find_holes (struct coverage const *cov,
   if (cov->size == 0)
     return hole (start, length, data);
 
-  uint64_t end (size_t i)
-  {
-    return cov->ranges[i].start + cov->ranges[i].length;
-  }
-
   if (start < cov->ranges[0].start)
     if (!hole (start, cov->ranges[0].start - start, data))
       return false;
 
   for (size_t i = 0; i < cov->size - 1; ++i)
     {
-      uint64_t end_i = end (i);
+      uint64_t end_i = cov->ranges[i].end ();
       if (!hole (end_i, cov->ranges[i+1].start - end_i, data))
        return false;
     }
 
-  if (start + length > end (cov->size - 1))
+  if (start + length > cov->back ().end ())
     {
-      uint64_t end_last = end (cov->size - 1);
+      uint64_t end_last = cov->back ().end ();
       return hole (end_last, start + length - end_last, data);
     }
 
@@ -310,26 +319,26 @@ coverage_free (struct coverage *cov)
   free (cov->ranges);
 }
 
-struct coverage *
+coverage *
 coverage_clone (struct coverage const *cov)
 {
-  struct coverage *ret = xmalloc (sizeof (*ret));
+  coverage *ret = (coverage *)xmalloc (sizeof (*ret));
   WIPE (*ret);
   coverage_add_all (ret, cov);
   return ret;
 }
 
 void
-coverage_add_all (struct coverage *restrict cov,
-                 struct coverage const *restrict other)
+coverage_add_all (struct coverage *__restrict__ cov,
+                 struct coverage const *__restrict__ other)
 {
   for (size_t i = 0; i < other->size; ++i)
     coverage_add (cov, other->ranges[i].start, other->ranges[i].length);
 }
 
 bool
-coverage_remove_all (struct coverage *restrict cov,
-                    struct coverage const *restrict other)
+coverage_remove_all (struct coverage *__restrict__ cov,
+                    struct coverage const *__restrict__ other)
 {
   bool ret = false;
   for (size_t i = 0; i < other->size; ++i)
index 26b732771b050ca524579264db1c4e1e8b49dbbe..ed4f00fe89cd4c59e7cd5df42d1d39cbeabc27e3 100644 (file)
@@ -41,8 +41,9 @@
          _a->alloc = 8;                                        \
        else                                                    \
          _a->alloc *= 2;                                       \
-       _a->BUF = xrealloc (_a->BUF,                            \
-                           sizeof (*_a->BUF) * _a->alloc);     \
+       _a->BUF = (typeof (_a->BUF))                            \
+         xrealloc (_a->BUF,                                    \
+                   sizeof (*_a->BUF) * _a->alloc);             \
       }                                                                \
   } while (0)
 
@@ -62,6 +63,10 @@ struct cov_range
 {
   uint64_t start;
   uint64_t length;
+
+#ifdef __cplusplus
+  uint64_t end () const { return start + length; }
+#endif
 };
 
 struct coverage
@@ -69,6 +74,11 @@ struct coverage
   struct cov_range *ranges;
   size_t size;
   size_t alloc;
+
+#ifdef __cplusplus
+  cov_range &back () { return ranges[size - 1]; }
+  cov_range const &back () const { return ranges[size - 1]; }
+#endif
 };
 
 struct coverage *coverage_clone (struct coverage const *cov)
diff --git a/src/dwarflint-coverage.hh b/src/dwarflint-coverage.hh
new file mode 100644 (file)
index 0000000..ec3a681
--- /dev/null
@@ -0,0 +1,95 @@
+/* Coverage analysis, C++ support.
+
+   Copyright (C) 2008,2009 Red Hat, Inc.
+   This file is part of Red Hat elfutils.
+
+   Red Hat elfutils is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by the
+   Free Software Foundation; version 2 of the License.
+
+   Red Hat elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Red Hat elfutils; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
+
+   Red Hat elfutils is an included package of the Open Invention Network.
+   An included package of the Open Invention Network is a package for which
+   Open Invention Network licensees cross-license their patents.  No patent
+   license is granted, either expressly or impliedly, by designation as an
+   included package.  Should you wish to participate in the Open Invention
+   Network licensing program, please visit www.openinventionnetwork.com
+   <http://www.openinventionnetwork.com>.  */
+
+#ifndef DWARFLINT_COVERAGE_HH
+#define DWARFLINT_COVERAGE_HH
+
+#include <string>
+#include <sstream>
+#include "dwarflint-coverage.h"
+
+namespace cov
+{
+  class _format_base
+  {
+  protected:
+    std::string const &_m_delim;
+    std::ostringstream _m_os;
+    bool _m_seen;
+
+    inline bool fmt (uint64_t start, uint64_t length)
+    {
+      if (_m_seen)
+       _m_os << _m_delim;
+      _m_os << "[" << start << ", " << start + length << ")";
+      _m_seen = true;
+      return true;
+    }
+
+    static bool
+    wrap_fmt (uint64_t start, uint64_t length, void *data)
+    {
+      _format_base *self = static_cast <_format_base *> (data);
+      return self->fmt (start, length);
+    }
+
+    _format_base (std::string const &delim)
+      : _m_delim (delim),
+       _m_seen (false)
+    {
+      _m_os << std::hex;
+    }
+
+  public:
+    operator std::string ()
+    {
+      return _m_os.str ();
+    }
+  };
+
+  struct format_ranges
+    : public _format_base
+  {
+    format_ranges (coverage const &cov, std::string const &delim = ", ")
+      : _format_base (delim)
+    {
+      coverage_find_ranges (&cov, &wrap_fmt, this);
+    }
+  };
+
+  struct format_holes
+    : public _format_base
+  {
+    format_holes (coverage const &cov, uint64_t start, uint64_t length,
+                 std::string const &delim = ", ")
+      : _format_base (delim)
+    {
+      coverage_find_holes (&cov, start, length, &wrap_fmt, this);
+    }
+  };
+}
+
+#endif//DWARFLINT_COVERAGE_HH