initial commit master
authorcamargo <camargo@lisha.ufsc.br>
Tue, 3 Jul 2018 18:44:50 +0000 (15:44 -0300)
committercamargo <camargo@lisha.ufsc.br>
Tue, 3 Jul 2018 18:44:50 +0000 (15:44 -0300)
README.md [new file with mode: 0644]
include/camargoutils/buffer.h [new file with mode: 0644]
include/camargoutils/proctimer.h [new file with mode: 0644]
include/camargoutils/stringutils.h [new file with mode: 0644]

diff --git a/README.md b/README.md
new file mode 100644 (file)
index 0000000..e907f2c
--- /dev/null
+++ b/README.md
@@ -0,0 +1,24 @@
+# libcamargoutils 
+
+This is a collection of C++ header-library utilities.
+
+Mostly made by me, some collected from the internet.
+
+
+## Copyrigfht and Credits
+
+### buffer.h
+
+```
+Copyright (c) 2011 Boris Kolpackov
+
+Distributed under the Boost Software License, Version 1.0. (See
+accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+
+Simple memory buffer abstraction. Version 1.0.0.
+```
+
+### All others
+
+Made by Lucas Camargo. Released under public domain.
diff --git a/include/camargoutils/buffer.h b/include/camargoutils/buffer.h
new file mode 100644 (file)
index 0000000..3e130a2
--- /dev/null
@@ -0,0 +1,401 @@
+#ifndef BUFFER_HPP_INCLUDED
+#define BUFFER_HPP_INCLUDED
+
+//
+//  buffer.hpp
+//
+//  Copyright (c) 2011 Boris Kolpackov
+//
+//  Distributed under the Boost Software License, Version 1.0. (See
+//  accompanying file LICENSE_1_0.txt or copy at
+//  http://www.boost.org/LICENSE_1_0.txt)
+//
+//  Simple memory buffer abstraction. Version 1.0.0.
+//
+
+#include <cstddef>   // std::size_t
+#include <cstring>   // std::memcpy, std::memcmp, std::memset, std::memchr
+#include <stdexcept> // std::out_of_range, std::invalid_argument
+
+namespace camargo {
+
+class buffer
+{
+public:
+  typedef std::size_t size_type;
+
+  static const size_type npos = static_cast<size_type> (-1);
+
+  ~buffer ();
+
+  explicit buffer (size_type size = 0);
+  buffer (size_type size, size_type capacity);
+  buffer (const void* data, size_type size);
+  buffer (const void* data, size_type size, size_type capacity);
+  buffer (void* data, size_type size, size_type capacity,
+          bool assume_ownership);
+
+  buffer (const buffer&);
+  buffer& operator= (const buffer&);
+
+  void swap (buffer&);
+  char* detach ();
+
+  void assign (const void* data, size_type size);
+  void assign (void* data, size_type size, size_type capacity,
+               bool assume_ownership);
+  void append (const buffer&);
+  void append (const void* data, size_type size);
+  void fill (char value = 0);
+
+  size_type size () const;
+  bool size (size_type);
+  size_type capacity () const;
+  bool capacity (size_type);
+  bool empty () const;
+  void clear ();
+
+  char* data ();
+  const char* data () const;
+
+  char& operator[] (size_type);
+  char operator[] (size_type) const;
+  char& at (size_type);
+  char at (size_type) const;
+
+  size_type find (char, size_type pos = 0) const;
+  size_type rfind (char, size_type pos = npos) const;
+
+private:
+  char* data_;
+  size_type size_;
+  size_type capacity_;
+  bool free_;
+};
+
+bool operator== (const buffer&, const buffer&);
+bool operator!= (const buffer&, const buffer&);
+
+//
+// Implementation.
+//
+inline buffer::~buffer ()
+{
+  if (free_)
+    delete[] data_;
+}
+
+inline buffer::buffer (size_type s)
+    : free_ (true)
+{
+  data_ = (s != 0 ? new char[s] : 0);
+  size_ = capacity_ = s;
+}
+
+inline buffer::buffer (size_type s, size_type c)
+    : free_ (true)
+{
+  if (s > c)
+    throw std::invalid_argument ("size greater than capacity");
+
+  data_ = (c != 0 ? new char[c] : 0);
+  size_ = s;
+  capacity_ = c;
+}
+
+inline buffer::buffer (const void* d, size_type s)
+    : free_ (true)
+{
+  if (s != 0)
+  {
+    data_ = new char[s];
+    std::memcpy (data_, d, s);
+  }
+  else
+    data_ = 0;
+
+  size_ = capacity_ = s;
+}
+
+inline buffer::buffer (const void* d, size_type s, size_type c)
+    : free_ (true)
+{
+  if (s > c)
+    throw std::invalid_argument ("size greater than capacity");
+
+  if (c != 0)
+  {
+    data_ = new char[c];
+
+    if (s != 0)
+      std::memcpy (data_, d, s);
+  }
+  else
+    data_ = 0;
+
+  size_ = s;
+  capacity_ = c;
+}
+
+inline buffer::buffer (void* d, size_type s, size_type c, bool own)
+    : data_ (static_cast<char*> (d)), size_ (s), capacity_ (c), free_ (own)
+{
+  if (s > c)
+    throw std::invalid_argument ("size greater than capacity");
+}
+
+inline buffer::buffer (const buffer& x)
+    : free_ (true)
+{
+  if (x.capacity_ != 0)
+  {
+    data_ = new char[x.capacity_];
+
+    if (x.size_ != 0)
+      std::memcpy (data_, x.data_, x.size_);
+  }
+  else
+    data_ = 0;
+
+  size_ = x.size_;
+  capacity_ = x.capacity_;
+}
+
+inline buffer& buffer::operator= (const buffer& x)
+{
+  if (&x != this)
+  {
+    if (x.size_ > capacity_)
+    {
+      if (free_)
+        delete[] data_;
+
+      data_ = new char[x.capacity_];
+      capacity_ = x.capacity_;
+      free_ = true;
+    }
+
+    if (x.size_ != 0)
+      std::memcpy (data_, x.data_, x.size_);
+
+    size_ = x.size_;
+  }
+
+  return *this;
+}
+
+inline void buffer::swap (buffer& x)
+{
+  char* d (x.data_);
+  size_type s (x.size_);
+  size_type c (x.capacity_);
+  bool f (x.free_);
+
+  x.data_ = data_;
+  x.size_ = size_;
+  x.capacity_ = capacity_;
+  x.free_ = free_;
+
+  data_ = d;
+  size_ = s;
+  capacity_ = c;
+  free_ = f;
+}
+
+inline char* buffer::detach ()
+{
+  char* r (data_);
+
+  data_ = 0;
+  size_ = 0;
+  capacity_ = 0;
+
+  return r;
+}
+
+inline void buffer::assign (const void* d, size_type s)
+{
+  if (s > capacity_)
+  {
+    if (free_)
+      delete[] data_;
+
+    data_ = new char[s];
+    capacity_ = s;
+    free_ = true;
+  }
+
+  if (s != 0)
+    std::memcpy (data_, d, s);
+
+  size_ = s;
+}
+
+inline void buffer::assign (void* d, size_type s, size_type c, bool own)
+{
+  if (free_)
+    delete[] data_;
+
+  data_ = static_cast<char*> (d);
+  size_ = s;
+  capacity_ = c;
+  free_ = own;
+}
+
+inline void buffer::append (const buffer& b)
+{
+  append (b.data (), b.size ());
+}
+
+inline void buffer::append (const void* d, size_type s)
+{
+  if (s != 0)
+  {
+    size_type ns (size_ + s);
+
+    if (capacity_ < ns)
+      capacity (ns);
+
+    std::memcpy (data_ + size_, d, s);
+    size_ = ns;
+  }
+}
+
+inline void buffer::fill (char v)
+{
+  if (size_ > 0)
+    std::memset (data_, v, size_);
+}
+
+inline buffer::size_type buffer::size () const
+{
+  return size_;
+}
+
+inline bool buffer::size (size_type s)
+{
+  bool r (false);
+
+  if (capacity_ < s)
+    r = capacity (s);
+
+  size_ = s;
+  return r;
+}
+
+inline buffer::size_type buffer::capacity () const
+{
+  return capacity_;
+}
+
+inline bool buffer::capacity (size_type c)
+{
+  // Ignore capacity decrease requests.
+  //
+  if (capacity_ >= c)
+    return false;
+
+  char* d (new char[c]);
+
+  if (size_ != 0)
+    std::memcpy (d, data_, size_);
+
+  if (free_)
+    delete[] data_;
+
+  data_ = d;
+  capacity_ = c;
+  free_ = true;
+
+  return true;
+}
+
+inline bool buffer::empty () const
+{
+  return size_ == 0;
+}
+
+inline void buffer::clear ()
+{
+  size_ = 0;
+}
+
+inline char* buffer::data ()
+{
+  return data_;
+}
+
+inline const char* buffer::data () const
+{
+  return data_;
+}
+
+inline char& buffer::operator[] (size_type i)
+{
+  return data_[i];
+}
+
+inline char buffer::operator[] (size_type i) const
+{
+  return data_[i];
+}
+
+inline char& buffer::at (size_type i)
+{
+  if (i >= size_)
+    throw std::out_of_range ("index out of range");
+
+  return data_[i];
+}
+
+inline char buffer::at (size_type i) const
+{
+  if (i >= size_)
+    throw std::out_of_range ("index out of range");
+
+  return data_[i];
+}
+
+inline buffer::size_type buffer::find (char v, size_type pos) const
+{
+  if (size_ == 0 || pos >= size_)
+    return npos;
+
+  char* p (static_cast<char*> (std::memchr (data_ + pos, v, size_ - pos)));
+  return p != 0 ? static_cast<size_type> (p - data_) : npos;
+}
+
+inline buffer::size_type buffer::rfind (char v, size_type pos) const
+{
+  // memrchr() is not standard.
+  //
+  if (size_ != 0)
+  {
+    size_type n (size_);
+
+    if (--n > pos)
+      n = pos;
+
+    for (++n; n-- != 0; )
+      if (data_[n] == v)
+        return n;
+  }
+
+  return npos;
+}
+
+inline bool operator== (const buffer& a, const buffer& b)
+{
+  return a.size () == b.size () &&
+    std::memcmp (a.data (), b.data (), a.size ()) == 0;
+}
+
+inline bool operator!= (const buffer& a, const buffer& b)
+{
+  return !(a == b);
+}
+
+} // namespace camargo
+
+#endif // BUFFER_HPP_INCLUDED
+
diff --git a/include/camargoutils/proctimer.h b/include/camargoutils/proctimer.h
new file mode 100644 (file)
index 0000000..6666148
--- /dev/null
@@ -0,0 +1,136 @@
+/**
+ * @file proctimer.h
+ * @brief Simple utility class to time sections of an execution with minimum 
+ *        overhead and good precision, using monotonic system clock deltas
+ * @author Lucas Pires Camargo 
+ * @copyright Public domain.
+ */
+
+#pragma once
+
+#include <vector>
+#include <utility>
+#include <cstdio>
+
+#include <stdint.h> // i`d use cstdint but that is c++11
+#include <time.h> // not std::chrono::steady_clock cause thats also c++11
+
+namespace camargo {
+
+class proctimer
+{
+public:
+    static const int CLOCK_DEF = CLOCK_MONOTONIC;
+    
+    proctimer()
+    {
+        m_total = 0;
+        
+        struct timespec ts;
+        clock_getres(CLOCK_DEF, &ts);
+        
+        m_precision = timespec_to_micros(&ts);
+    }
+    
+    ~proctimer()
+    {
+        // nothing to do here for now
+    }
+    
+    typedef std::pair< const char*, uint64_t > section_timing;
+    typedef std::vector<section_timing> timings;
+    
+    void clear() 
+    { 
+        m_timings.clear(); 
+    }
+    
+    void begin_section(const char *sectionName)
+    {
+        uint64_t now = get_now();
+        
+        if(m_timings.size())
+        {
+            // finish up previous timing
+            section_timing &last = m_timings[m_timings.size() - 1];
+            last.second = now - last.second;
+        }
+        
+        m_timings.push_back(section_timing(sectionName, now));
+    }
+    
+    void finish()
+    {
+        if(!m_timings.size())
+        {
+            m_total = 0;
+            return;
+        }
+        
+        // finish up last item
+        uint64_t now = get_now();
+        section_timing &last = m_timings[m_timings.size() - 1];
+        last.second = now - last.second;
+        
+        // now, calculate total time
+        uint64_t total_micros = 0;
+        for(timings::iterator it =m_timings.begin(); it < m_timings.end(); it++)
+        {
+            total_micros += it->second;
+        }
+        
+        m_total = total_micros;
+    }
+    
+    uint64_t get_total_micros()
+    {
+        return m_total;
+    }
+    
+    timings get_timings() 
+    {
+        return m_timings;
+    }
+    
+    void output_report(int fd, bool detailed = true)
+    {
+        // fd is the file descriptor
+        dprintf(fd, "\n================\nproctimer report\n");
+        dprintf(fd, "total time: %f ms\n", m_total/1000.0f);
+        
+        if(!detailed) return;
+        
+        dprintf(fd, "clock precision: %f ms\n", m_precision/1000.0f);
+        
+        for(timings::iterator it =m_timings.begin(); it < m_timings.end(); it++)
+        {
+            
+            dprintf(fd, "section '%s': %f ms\n", it->first, (it->second)/1000.0f);
+        }
+        
+    }
+    
+private:
+    static uint64_t timespec_to_micros( struct timespec *ts )
+    {
+        return ts->tv_sec * 1e6 + ts->tv_nsec/1000;
+    }
+    
+    uint64_t get_now()
+    {
+        struct timespec ts;
+        int ret = clock_gettime(CLOCK_DEF, &ts);
+        
+        if(!ret)
+        {
+            return timespec_to_micros(&ts);
+        }
+        else return -1;
+    }
+    
+    timings m_timings;
+    uint64_t m_total;
+    uint64_t m_precision;
+};
+
+}
diff --git a/include/camargoutils/stringutils.h b/include/camargoutils/stringutils.h
new file mode 100644 (file)
index 0000000..b336b88
--- /dev/null
@@ -0,0 +1,30 @@
+#pragma once
+
+/**
+ * From somewhere on the internet (Stack Overflow maybe?)
+ */
+
+#include <string>
+#include <vector>
+
+namespace camargo
+{
+
+    inline std::vector<std::string> strsplit(const char *str, char c = ' ')
+    {
+        std::vector<std::string> result;
+        
+        do
+        {
+            const char *begin = str;
+            
+            while(*str != c && *str)
+                str++;
+            
+            result.push_back(string(begin, str));
+        } while (0 != *str++);
+        
+        return result;
+    } 
+
+}