
use io
use mem

+ pointer ptr {
    + fn to_hex() String $to {
        return (this.@cast(uint)).to_hex()
    }

    fn print() {
        (this.@cast(uint)).print(16)
    }

    fn print_content(length: uint) {
        io:print_from_ptr(this, length)
    }

    + fn index_of_byte(byte: u8, memory_size: uint) uint !not_found {
        let index : uint = 0
        let len = memory_size
        while index < len {
            let ch = @ptrv(this, u8, index)
            if ch == byte : return index
            index++
        }
        throw not_found
    }

    + fn print_bytes(length: uint, end_with_newline: bool (true)) {
        let adr = this
        while length-- > 0 {
            print("0x")
            @ptrv(adr, u8).print(16)
            adr += 1
            if length > 0 : print(",")
        }
        if end_with_newline : print("\n")
    }

    fn create_string(length: uint) String {
        if length == 0 : return ""
        let str = String.make_empty(length)
        mem:copy(this, str.data, length)
        return str
    }

    + fn offset(offset: int) ptr {
        return @offset(this, u8, offset)
    }

    fn read_uint_value(len: uint) uint !invalid {
        let i = len
        if i == 0 : throw invalid
        let result : uint = 0
        let mult : uint = 1

        while i > 0 {
            let ch = @ptrv(this, u8, --i)
            let v = ch - '0'
            if v > 9 : throw invalid
            result += v.@cast(uint) * mult
            mult *= 10
        }
        return result
    }

    fn read_octal_value(len: uint) uint !invalid {
        let i = len
        if i == 0 : throw invalid
        let result : uint = 0
        let mult : uint = 1

        while i > 0 {
            let ch = @ptrv(this, u8, --i)
            if ch >= '0' && ch <= '7' {
                result += ((ch.@cast(uint)) - '0') * mult
            } else if ch == 'c' && i == 1 && @ptrv(this, u8, 0) == '0' {
                break
            } else {
                throw invalid
            }
            mult *= 8
        }
        return result
    }

    fn read_hex_value(len: uint) uint !invalid {
        let i = len
        if i == 0 : throw invalid
        let result : uint = 0
        let mult : uint = 1

        while i > 0 {
            let ch = @ptrv(this, u8, --i)
            if ch >= '0' && ch <= '9' {
                result += ((ch.@cast(uint)) - '0') * mult
            } else if ch >= 'A' && ch <= 'F' {
                result += ((ch.@cast(uint)) - 'A' + 10) * mult
            } else if ch >= 'a' && ch <= 'f' {
                result += ((ch.@cast(uint)) - 'a' + 10) * mult
            } else if ch == 'x' && i == 1 && @ptrv(this, u8, 0) == '0' {
                break
            } else {
                throw invalid
            }
            mult *= 16
        }
        return result
    }
}
