// Copyright 2019 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//go:build !windows
// +build !windows

package procfs

import (
	
	
	
	
	

	
)

// Zoneinfo holds info parsed from /proc/zoneinfo.
type Zoneinfo struct {
	Node                       string
	Zone                       string
	NrFreePages                *int64
	Min                        *int64
	Low                        *int64
	High                       *int64
	Scanned                    *int64
	Spanned                    *int64
	Present                    *int64
	Managed                    *int64
	NrActiveAnon               *int64
	NrInactiveAnon             *int64
	NrIsolatedAnon             *int64
	NrAnonPages                *int64
	NrAnonTransparentHugepages *int64
	NrActiveFile               *int64
	NrInactiveFile             *int64
	NrIsolatedFile             *int64
	NrFilePages                *int64
	NrSlabReclaimable          *int64
	NrSlabUnreclaimable        *int64
	NrMlockStack               *int64
	NrKernelStack              *int64
	NrMapped                   *int64
	NrDirty                    *int64
	NrWriteback                *int64
	NrUnevictable              *int64
	NrShmem                    *int64
	NrDirtied                  *int64
	NrWritten                  *int64
	NumaHit                    *int64
	NumaMiss                   *int64
	NumaForeign                *int64
	NumaInterleave             *int64
	NumaLocal                  *int64
	NumaOther                  *int64
	Protection                 []*int64
}

var nodeZoneRE = regexp.MustCompile(`(\d+), zone\s+(\w+)`)

// Zoneinfo parses an zoneinfo-file (/proc/zoneinfo) and returns a slice of
// structs containing the relevant info.  More information available here:
// https://www.kernel.org/doc/Documentation/sysctl/vm.txt
func ( FS) () ([]Zoneinfo, error) {
	,  := os.ReadFile(.proc.Path("zoneinfo"))
	if  != nil {
		return nil, fmt.Errorf("%w: error reading zoneinfo %q: %w", ErrFileRead, .proc.Path("zoneinfo"), )
	}
	,  := parseZoneinfo()
	if  != nil {
		return nil, fmt.Errorf("%w: error parsing zoneinfo %q: %w", ErrFileParse, .proc.Path("zoneinfo"), )
	}
	return , nil
}

func parseZoneinfo( []byte) ([]Zoneinfo, error) {

	 := []Zoneinfo{}

	 := bytes.Split(, []byte("\nNode"))
	for ,  := range  {
		var  Zoneinfo
		 := strings.Split(string(), "\n")
		for ,  := range  {

			if  := nodeZoneRE.FindStringSubmatch();  != nil {
				.Node = [1]
				.Zone = [2]
				continue
			}
			if strings.HasPrefix(strings.TrimSpace(), "per-node stats") {
				continue
			}
			 := strings.Fields(strings.TrimSpace())
			if len() < 2 {
				continue
			}
			 := util.NewValueParser([1])
			switch [0] {
			case "nr_free_pages":
				.NrFreePages = .PInt64()
			case "min":
				.Min = .PInt64()
			case "low":
				.Low = .PInt64()
			case "high":
				.High = .PInt64()
			case "scanned":
				.Scanned = .PInt64()
			case "spanned":
				.Spanned = .PInt64()
			case "present":
				.Present = .PInt64()
			case "managed":
				.Managed = .PInt64()
			case "nr_active_anon":
				.NrActiveAnon = .PInt64()
			case "nr_inactive_anon":
				.NrInactiveAnon = .PInt64()
			case "nr_isolated_anon":
				.NrIsolatedAnon = .PInt64()
			case "nr_anon_pages":
				.NrAnonPages = .PInt64()
			case "nr_anon_transparent_hugepages":
				.NrAnonTransparentHugepages = .PInt64()
			case "nr_active_file":
				.NrActiveFile = .PInt64()
			case "nr_inactive_file":
				.NrInactiveFile = .PInt64()
			case "nr_isolated_file":
				.NrIsolatedFile = .PInt64()
			case "nr_file_pages":
				.NrFilePages = .PInt64()
			case "nr_slab_reclaimable":
				.NrSlabReclaimable = .PInt64()
			case "nr_slab_unreclaimable":
				.NrSlabUnreclaimable = .PInt64()
			case "nr_mlock_stack":
				.NrMlockStack = .PInt64()
			case "nr_kernel_stack":
				.NrKernelStack = .PInt64()
			case "nr_mapped":
				.NrMapped = .PInt64()
			case "nr_dirty":
				.NrDirty = .PInt64()
			case "nr_writeback":
				.NrWriteback = .PInt64()
			case "nr_unevictable":
				.NrUnevictable = .PInt64()
			case "nr_shmem":
				.NrShmem = .PInt64()
			case "nr_dirtied":
				.NrDirtied = .PInt64()
			case "nr_written":
				.NrWritten = .PInt64()
			case "numa_hit":
				.NumaHit = .PInt64()
			case "numa_miss":
				.NumaMiss = .PInt64()
			case "numa_foreign":
				.NumaForeign = .PInt64()
			case "numa_interleave":
				.NumaInterleave = .PInt64()
			case "numa_local":
				.NumaLocal = .PInt64()
			case "numa_other":
				.NumaOther = .PInt64()
			case "protection:":
				 := strings.Split(, ":")
				 := strings.Replace([1], "(", "", 1)
				 = strings.Replace(, ")", "", 1)
				 = strings.TrimSpace()
				 := strings.Split(, ", ")
				,  := util.ParsePInt64s()
				if  == nil {
					.Protection = 
				}
			}

		}

		 = append(, )
	}
	return , nil
}