#ifndef MEMMAP_HPP
#define MEMMAP_HPP 1

#include <ostream>
#include <vector>
#include <string>
#include <map>

struct Sym;
class Syms;

struct MapEntry
{
  MapEntry():upper_(),lower_(),table_(),isExe_(false) { }
  MapEntry(void* upper,void* lower,const std::string& filename)
      : upper_((unsigned long)upper)
      , lower_((unsigned long)lower)
      , file_(filename)
      , table_()
      , isExe_(false) { }

  unsigned long upper_;
  unsigned long lower_;
  std::string file_;
  Syms* table_;
  bool isExe_;

  bool operator<(unsigned long addr) const
    {
      return lower_ < addr;
    }
  bool operator<(const MapEntry& b) const
    {
      return lower_ < b.lower_;
    }
};

std::ostream& operator<<(std::ostream& ost, const MapEntry& m);
inline bool operator<(unsigned long addr,const MapEntry& m)
{ return addr < m.lower_; }

class MemMap
{
public:
  typedef std::vector<MapEntry> EntryVec;
  typedef std::map<std::string,Syms*> SymsMap;

  MemMap(const char* filename, const char* exename);
  ~MemMap();

  const Sym* resolve(unsigned long address) const;

  void print(std::ostream& ost) const;

private:
  Syms* getCached(const std::string& filename, int offset) const;
  mutable SymsMap cache_;
  mutable EntryVec entries_;
};

inline std::ostream& operator<<(std::ostream& ost, const MemMap& m)
{
  m.print(ost);
  return ost;
}

#endif
