<commit_before>// Copyright 2013 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package goproperties

import (
	"fmt"
	"io"
	"strconv"
	"strings"
	"unicode/utf8"
)

type Properties struct {
	// Pre-/Postfix for property expansion.
	Prefix  string
	Postfix string

	m map[string]string
}

// NewProperties creates a new Properties struct with the default
// configuration for "${key}" expressions.
func NewProperties() *Properties {
	return &Properties{
		Prefix:  "${",
		Postfix: "}",
		m:       make(map[string]string),
	}
}

// Get returns the expanded value for the given key if exists. Otherwise, ok is false.
func (p *Properties) Get(key string) (value string, ok bool) {
	v, ok := p.m[key]
	if !ok {
		return "", false
	}

	expanded, err := p.expand(v)

	// we guarantee that the expanded value is free of
	// circular references and malformed expressions
	// so we panic if we still get an error here.
	if err != nil {
		panic(fmt.Errorf("%s in %q", err, key+" = "+v))
	}

	return expanded, true
}

// GetBool checks if the expanded value is one of '1', 'yes',
// 'true' or 'on' if the key exists. The comparison is case-insensitive.
// If the key does not exist the default value is returned.
func (p *Properties) GetBool(key string, def bool) bool {
	if v, ok := p.Get(key); ok {
		v = strings.ToLower(v)
		return v == "1" || v == "true" || v == "yes" || v == "on"
	}
	return def
}

// GetFloat64 parses the expanded value as a float64 if the key exists.
// If key does not exist or the value cannot be parsed the default
// value is returned.
func (p *Properties) GetFloat64(key string, def float64) float64 {
	if v, ok := p.Get(key); ok {
		n, err := strconv.ParseFloat(v, 64)
		if err != nil {
			return def
		}
		return n
	}
	return def
}

// GetInt64 parses the expanded value as an int if the key exists.
// If key does not exist or the value cannot be parsed the default
// value is returned.
func (p *Properties) GetInt64(key string, def int64) int64 {
	if v, ok := p.Get(key); ok {
		n, err := strconv.ParseInt(v, 10, 64)
		if err != nil {
			return def
		}
		return n
	}
	return def
}

// GetUint64 parses the expanded value as an uint64 if the key exists.
// If key does not exist or the value cannot be parsed the default
// value is returned.
func (p *Properties) GetUint64(key string, def uint64) uint64 {
	if v, ok := p.Get(key); ok {
		n, err := strconv.ParseUint(v, 10, 64)
		if err != nil {
			return def
		}
		return n
	}
	return def
}

// GetString returns the expanded value for the given key if exists or the default value otherwise.
func (p *Properties) GetString(key, def string) string {
	if v, ok := p.Get(key); ok {
		return v
	}
	return def
}

// Len returns the number of keys.
func (p *Properties) Len() int {
	return len(p.m)
}

// Set sets the property key to the corresponding value.
// If a value for key existed before then ok is true and prev
// contains the previous value. If the value contains a
// circular reference or a malformed expression then
// an error is returned.
func (p *Properties) Set(key, value string) (prev string, ok bool, err error) {
	// TODO(frank): Check for invalid unicode literals since this is currently done in the lexer.
	_, err = p.expand(value)
	if err != nil {
		return "", false, err
	}

	v, ok := p.Get(key)<commit_msg>Replace TODO with proper BUG comments.<commit_after>// Copyright 2013 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package goproperties

// BUG(frank): Set() does not check for invalid unicode literals since this is currently handled by the lexer.
// BUG(frank): Write() does not allow to configure the newline character. Therefore, on Windows LF is used.

import (
	"fmt"
	"io"
	"strconv"
	"strings"
	"unicode/utf8"
)

type Properties struct {
	// Pre-/Postfix for property expansion.
	Prefix  string
	Postfix string

	m map[string]string
}

// NewProperties creates a new Properties struct with the default
// configuration for "${key}" expressions.
func NewProperties() *Properties {
	return &Properties{
		Prefix:  "${",
		Postfix: "}",
		m:       make(map[string]string),
	}
}

// Get returns the expanded value for the given key if exists. Otherwise, ok is false.
func (p *Properties) Get(key string) (value string, ok bool) {
	v, ok := p.m[key]
	if !ok {
		return "", false
	}

	expanded, err := p.expand(v)

	// we guarantee that the expanded value is free of
	// circular references and malformed expressions
	// so we panic if we still get an error here.
	if err != nil {
		panic(fmt.Errorf("%s in %q", err, key+" = "+v))
	}

	return expanded, true
}

// GetBool checks if the expanded value is one of '1', 'yes',
// 'true' or 'on' if the key exists. The comparison is case-insensitive.
// If the key does not exist the default value is returned.
func (p *Properties) GetBool(key string, def bool) bool {
	if v, ok := p.Get(key); ok {
		v = strings.ToLower(v)
		return v == "1" || v == "true" || v == "yes" || v == "on"
	}
	return def
}

// GetFloat64 parses the expanded value as a float64 if the key exists.
// If key does not exist or the value cannot be parsed the default
// value is returned.
func (p *Properties) GetFloat64(key string, def float64) float64 {
	if v, ok := p.Get(key); ok {
		n, err := strconv.ParseFloat(v, 64)
		if err != nil {
			return def
		}
		return n
	}
	return def
}

// GetInt64 parses the expanded value as an int if the key exists.
// If key does not exist or the value cannot be parsed the default
// value is returned.
func (p *Properties) GetInt64(key string, def int64) int64 {
	if v, ok := p.Get(key); ok {
		n, err := strconv.ParseInt(v, 10, 64)
		if err != nil {
			return def
		}
		return n
	}
	return def
}

// GetUint64 parses the expanded value as an uint64 if the key exists.
// If key does not exist or the value cannot be parsed the default
// value is returned.
func (p *Properties) GetUint64(key string, def uint64) uint64 {
	if v, ok := p.Get(key); ok {
		n, err := strconv.ParseUint(v, 10, 64)
		if err != nil {
			return def
		}
		return n
	}
	return def
}

// GetString returns the expanded value for the given key if exists or the default value otherwise.
func (p *Properties) GetString(key, def string) string {
	if v, ok := p.Get(key); ok {
		return v
	}
	return def
}

// Len returns the number of keys.
func (p *Properties) Len() int {
	return len(p.m)
}

// Set sets the property key to the corresponding value.
// If a value for key existed before then ok is true and prev
// contains the previous value. If the value contains a
// circular reference or a malformed expression then
// an error is returned.
func (p *Properties) Set(key, value string) (prev string, ok bool, err error) {
	_, err = p.expand(value)
	if err != nil {
		return "", false, err
	}

	v, ok := p.Get(key)
{'fraction_non_alphanumeric': 0.1139185677158533, 'fraction_numerical': 0.012994513427663876, 'mean_word_length': 3.1956390066626286, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3459109', 'n_tokens_mistral': 2341, 'n_tokens_neox': 2212, 'n_words': 1001}