#pragma once
#ifndef __AUTO_RANGE__
#define __AUTO_RANGE__
#include "AutoDefs.h"
namespace Auto {
class Range {
private:
void *_address; void *_end;
public:
Range() : _address(NULL), _end(NULL) {}
Range(void *address) : _address(address), _end(address) {}
Range(void *address, void *end) : _address(address), _end(end) {}
Range(void *address, usword_t size) : _address(address), _end(displace(address, size)) {}
inline Range& range() { return *this; }
inline void *address() const { return _address; }
inline void *end() const { return _end; }
inline const usword_t size() const { return (uintptr_t)_end - (uintptr_t)_address; }
inline void set_address(void *address) { _address = address; }
inline void set_end(void *end) { _end = end; }
inline void set_size(usword_t size) { _end = displace(_address, size); }
inline void set_range(void *address, void *end) { _address = address; _end = end; }
inline void set_range(void *address, usword_t size) { _address = address; _end = displace(address, size); }
inline void adjust_address(intptr_t delta) { _address = displace(_address, delta); }
inline void adjust_end(intptr_t delta) { _end = displace(_end, delta); }
inline void adjust(intptr_t delta) { _address = displace(_address, delta), _end = displace(_end, delta); }
inline bool is_empty() { return _address == _end; }
static inline const bool in_range(void *lo, void *hi, void *address) {
uintptr_t lo_as_int = (uintptr_t)lo;
uintptr_t hi_as_int = (uintptr_t)hi;
uintptr_t diff = hi_as_int - lo_as_int;
uintptr_t address_as_int = (uintptr_t)address;
return (address_as_int - lo_as_int) < diff;
}
inline const bool in_range(void *address) const { return in_range(_address, _end, address); }
inline const bool operator==(const Range *range) const { return _address == range->_address; }
inline const bool operator==(const Range &range) const { return _address == range._address; }
inline const bool is_range(const Range& range) const { return _address == range._address && _end == range._end; }
inline void clear() { bzero(address(), size()); }
inline void expand_range(void *address) {
if (_address > address) _address = address;
if (_end < address) _end = address;
}
inline void expand_range(Range& range) {
expand_range(range.address());
expand_range(range.end());
}
inline void *relative_address(void *address) const { return (void *)((uintptr_t)address - (uintptr_t)_address); }
inline void *absolute_address(void *address) const { return (void *)((uintptr_t)address + (uintptr_t)_address); }
};
};
#endif // __AUTO_RANGE__