blob: 799cd7c8ac626eefb9449710b3d769b36355847f [file] [log] [blame]
Nigel Taoeb7c1fa2015-08-26 17:05:26 +10001// Copyright 2015 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
Russ Cox85be41e2021-02-19 18:54:48 -05005//go:build !linux && !windows && !darwin
Nigel Taoeb7c1fa2015-08-26 17:05:26 +10006
7// Package mmap provides a way to memory-map a file.
8package mmap
9
10import (
11 "fmt"
12 "os"
13)
14
15// ReaderAt reads a memory-mapped file.
16//
17// Like any io.ReaderAt, clients can execute parallel ReadAt calls, but it is
18// not safe to call Close and reading methods concurrently.
19type ReaderAt struct {
20 f *os.File
21 len int
22}
23
24// Close closes the reader.
25func (r *ReaderAt) Close() error {
26 return r.f.Close()
27}
28
29// Len returns the length of the underlying memory-mapped file.
30func (r *ReaderAt) Len() int {
31 return r.len
32}
33
34// At returns the byte at index i.
35func (r *ReaderAt) At(i int) byte {
36 if i < 0 || r.len <= i {
37 panic("index out of range")
38 }
39 var b [1]byte
40 r.ReadAt(b[:], int64(i))
41 return b[0]
42}
43
44// ReadAt implements the io.ReaderAt interface.
45func (r *ReaderAt) ReadAt(p []byte, off int64) (int, error) {
46 return r.f.ReadAt(p, off)
47}
48
49// Open memory-maps the named file for reading.
50func Open(filename string) (*ReaderAt, error) {
51 f, err := os.Open(filename)
52 if err != nil {
53 return nil, err
54 }
55 fi, err := f.Stat()
56 if err != nil {
57 f.Close()
58 return nil, err
59 }
60
61 size := fi.Size()
62 if size < 0 {
63 f.Close()
64 return nil, fmt.Errorf("mmap: file %q has negative size", filename)
65 }
66 if size != int64(int(size)) {
67 f.Close()
68 return nil, fmt.Errorf("mmap: file %q is too large", filename)
69 }
70
71 return &ReaderAt{
72 f: f,
73 len: int(fi.Size()),
74 }, nil
75}