提交 473e0fcf 编写于 作者: chai2010's avatar chai2010

切换到新 waroot 目录, 删除旧目录

上级 4aa6f295
......@@ -10,7 +10,7 @@ import (
"text/template"
"time"
"wa-lang.org/wa/internal/waroot"
"wa-lang.org/wa/waroot"
)
func (p *App) InitApp(name, pkgpath string, update bool) error {
......
......@@ -11,7 +11,7 @@ import (
"wa-lang.org/wa/internal/config"
"wa-lang.org/wa/internal/loader"
"wa-lang.org/wa/internal/ssa"
"wa-lang.org/wa/internal/waroot"
"wa-lang.org/wa/waroot"
)
type Compiler struct {
......
......@@ -20,7 +20,7 @@ import (
"wa-lang.org/wa/internal/ssa"
"wa-lang.org/wa/internal/token"
"wa-lang.org/wa/internal/types"
"wa-lang.org/wa/internal/waroot"
"wa-lang.org/wa/waroot"
)
type _Loader struct {
......
......@@ -13,7 +13,7 @@ import (
"wa-lang.org/wa/internal/config"
"wa-lang.org/wa/internal/logger"
"wa-lang.org/wa/internal/waroot"
"wa-lang.org/wa/waroot"
)
// 根据路径加载需要的 vfs 和 manifest
......
版权 @{{.Year}} {{.Name}} 作者。保留所有权利。
# Pkg: {{.Name}}
欢迎使用 Wa 语言!
```
+---+ +---+
| o | | o |
| +----+ |
| |
| \/\/ |
| |
+------------+
```
// 版权 @{{.Year}} {{.Name}} 作者。保留所有权利。
func main {
println("你好,凹语言!")
println(sum(100))
heart()
}
func sum(n: int) => int {
var v: int
for i := 1; i <= n; i++ {
v += i
}
return v
}
func heart {
a := 0.0
for y := 1.5; y > -1.5; y = y - 0.1 {
for x := -1.5; x < 1.5; x = x + 0.05 {
a = x*x + y*y - 1.0
if a*a*a < x*x*y*y*y {
print('@')
} else {
print(' ')
}
}
println()
}
}
// 版权 @{{.Year}} {{.Name}} 作者。保留所有权利。
// 打印素数
func PrintPrime(max: int) {
for n := 2; n <= max; n = n + 1 {
isPrime := 1
for i := 2; i*i <= n; i = i + 1 {
if x := n % i; x == 0 {
isPrime = 0
}
}
if isPrime != 0 {
println(n)
}
}
}
// 版权 @{{.Year}} {{.Name}} 作者。保留所有权利。
// 打印整数
func Println(x: int) {
println(x)
}
{
"name": "{{.Name}}",
"pkgpath": "{{.Pkgpath}}",
"version": "0.0.1",
"authors": ["author", "author2"],
"description": "module description",
"readme": "README.md",
"homepage": "",
"repository": "",
"license": "",
"license_file": "LICENSE",
"keywords": [],
"categories": []
}
// 版权 @{{.Year}} {{.Name}} 作者。保留所有权利。
func Println(x: int) {
println(x)
}
// 版权 @2023 凹语言 作者。保留所有权利。
// Package binary implements simple translation between numbers and byte
// sequences and encoding and decoding of varints.
//
// Numbers are translated by reading and writing fixed-size values.
// A fixed-size value is either a fixed-size arithmetic
// type (bool, int8, uint8, int16, float32, complex64, ...)
// or an array or struct containing only fixed-size values.
//
// The varint functions encode and decode single integer values using
// a variable-length encoding; smaller values require fewer bytes.
// For a specification, see
// https://developers.google.com/protocol-buffers/docs/encoding.
//
// This package favors simplicity over efficiency. Clients that require
// high-performance serialization, especially for large data structures,
// should look at more advanced solutions such as the encoding/gob
// package or protocol buffers.
import (
//"errors"
//"io"
//"math"
)
// A ByteOrder specifies how to convert byte sequences into
// 16-, 32-, or 64-bit unsigned integers.
type ByteOrder interface {
Uint16(b: []byte) => u16
Uint32(b: []byte) => u32
Uint64(b: []byte) => u64
PutUint16(b: []byte, v: u16)
PutUint32(b: []byte, v: u32)
PutUint64(b: []byte, v: u64)
String() => string
}
// LittleEndian is the little-endian implementation of ByteOrder.
var LittleEndian = &littleEndian{}
// BigEndian is the big-endian implementation of ByteOrder.
var BigEndian = &bigEndian{}
type littleEndian struct{}
func littleEndian.Uint16(b: []byte) => u16 {
_ = b[1] // bounds check hint to compiler; see golang.org/issue/14808
return u16(b[0]) | u16(b[1])<<8
}
func littleEndian.PutUint16(b: []byte, v: u16) {
_ = b[1] // early bounds check to guarantee safety of writes below
b[0] = byte(v)
b[1] = byte(v >> 8)
}
func littleEndian.Uint32(b: []byte) => u32 {
_ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
return u32(b[0]) | u32(b[1])<<8 | u32(b[2])<<16 | u32(b[3])<<24
}
func littleEndian.PutUint32(b: []byte, v: u32) {
_ = b[3] // early bounds check to guarantee safety of writes below
b[0] = byte(v)
b[1] = byte(v >> 8)
b[2] = byte(v >> 16)
b[3] = byte(v >> 24)
}
func littleEndian.Uint64(b: []byte) => u64 {
_ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
return u64(b[0]) | u64(b[1])<<8 | u64(b[2])<<16 | u64(b[3])<<24 |
u64(b[4])<<32 | u64(b[5])<<40 | u64(b[6])<<48 | u64(b[7])<<56
}
func littleEndian.PutUint64(b: []byte, v: u64) {
_ = b[7] // early bounds check to guarantee safety of writes below
b[0] = byte(v)
b[1] = byte(v >> 8)
b[2] = byte(v >> 16)
b[3] = byte(v >> 24)
b[4] = byte(v >> 32)
b[5] = byte(v >> 40)
b[6] = byte(v >> 48)
b[7] = byte(v >> 56)
}
func littleEndian.String => string { return "LittleEndian" }
func littleEndian.WaString => string { return "binary.LittleEndian" }
type bigEndian struct{}
func bigEndian.Uint16(b: []byte) => u16 {
_ = b[1] // bounds check hint to compiler; see golang.org/issue/14808
return u16(b[1]) | u16(b[0])<<8
}
func bigEndian.PutUint16(b: []byte, v: u16) {
_ = b[1] // early bounds check to guarantee safety of writes below
b[0] = byte(v >> 8)
b[1] = byte(v)
}
func bigEndian.Uint32(b: []byte) => u32 {
_ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
return u32(b[3]) | u32(b[2])<<8 | u32(b[1])<<16 | u32(b[0])<<24
}
func bigEndian.PutUint32(b: []byte, v: u32) {
_ = b[3] // early bounds check to guarantee safety of writes below
b[0] = byte(v >> 24)
b[1] = byte(v >> 16)
b[2] = byte(v >> 8)
b[3] = byte(v)
}
func bigEndian.Uint64(b: []byte) => u64 {
_ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
return u64(b[7]) | u64(b[6])<<8 | u64(b[5])<<16 | u64(b[4])<<24 |
u64(b[3])<<32 | u64(b[2])<<40 | u64(b[1])<<48 | u64(b[0])<<56
}
func bigEndian.PutUint64(b: []byte, v: u64) {
_ = b[7] // early bounds check to guarantee safety of writes below
b[0] = byte(v >> 56)
b[1] = byte(v >> 48)
b[2] = byte(v >> 40)
b[3] = byte(v >> 32)
b[4] = byte(v >> 24)
b[5] = byte(v >> 16)
b[6] = byte(v >> 8)
b[7] = byte(v)
}
func bigEndian.String => string { return "BigEndian" }
func bigEndian.WaString => string { return "binary.BigEndian" }
/*
// Read reads structured binary data from r into data.
// Data must be a pointer to a fixed-size value or a slice
// of fixed-size values.
// Bytes read from r are decoded using the specified byte order
// and written to successive fields of the data.
// When decoding boolean values, a zero byte is decoded as false, and
// any other non-zero byte is decoded as true.
// When reading into structs, the field data for fields with
// blank (_) field names is skipped; i.e., blank field names
// may be used for padding.
// When reading into a struct, all non-blank fields must be exported
// or Read may panic.
//
// The error is EOF only if no bytes were read.
// If an EOF happens after reading some but not all the bytes,
// Read returns ErrUnexpectedEOF.
func Read(r io.Reader, order ByteOrder, data interface{}) error {
// Fast path for basic types and slices.
if n := intDataSize(data); n != 0 {
bs := make([]byte, n)
if _, err := io.ReadFull(r, bs); err != nil {
return err
}
switch data := data.(type) {
case *bool:
*data = bs[0] != 0
case *int8:
*data = int8(bs[0])
case *uint8:
*data = bs[0]
case *int16:
*data = int16(order.Uint16(bs))
case *u16:
*data = order.Uint16(bs)
case *int32:
*data = int32(order.Uint32(bs))
case *u32:
*data = order.Uint32(bs)
case *int64:
*data = int64(order.Uint64(bs))
case *u64:
*data = order.Uint64(bs)
case *float32:
*data = math.Float32frombits(order.Uint32(bs))
case *float64:
*data = math.Float64frombits(order.Uint64(bs))
case []bool:
for i, x := range bs { // Easier to loop over the input for 8-bit values.
data[i] = x != 0
}
case []int8:
for i, x := range bs {
data[i] = int8(x)
}
case []uint8:
copy(data, bs)
case []int16:
for i := range data {
data[i] = int16(order.Uint16(bs[2*i:]))
}
case []u16:
for i := range data {
data[i] = order.Uint16(bs[2*i:])
}
case []int32:
for i := range data {
data[i] = int32(order.Uint32(bs[4*i:]))
}
case []u32:
for i := range data {
data[i] = order.Uint32(bs[4*i:])
}
case []int64:
for i := range data {
data[i] = int64(order.Uint64(bs[8*i:]))
}
case []u64:
for i := range data {
data[i] = order.Uint64(bs[8*i:])
}
case []float32:
for i := range data {
data[i] = math.Float32frombits(order.Uint32(bs[4*i:]))
}
case []float64:
for i := range data {
data[i] = math.Float64frombits(order.Uint64(bs[8*i:]))
}
default:
n = 0 // fast path doesn't apply
}
if n != 0 {
return nil
}
}
// Fallback to reflect-based decoding.
v := reflect.ValueOf(data)
size := -1
switch v.Kind() {
case reflect.Ptr:
v = v.Elem()
size = dataSize(v)
case reflect.Slice:
size = dataSize(v)
}
if size < 0 {
return errors.New("binary.Read: invalid type " + reflect.TypeOf(data).String())
}
d := &decoder{order: order, buf: make([]byte, size)}
if _, err := io.ReadFull(r, d.buf); err != nil {
return err
}
d.value(v)
return nil
}
// Write writes the binary representation of data into w.
// Data must be a fixed-size value or a slice of fixed-size
// values, or a pointer to such data.
// Boolean values encode as one byte: 1 for true, and 0 for false.
// Bytes written to w are encoded using the specified byte order
// and read from successive fields of the data.
// When writing structs, zero values are written for fields
// with blank (_) field names.
func Write(w io.Writer, order ByteOrder, data interface{}) error {
// Fast path for basic types and slices.
if n := intDataSize(data); n != 0 {
bs := make([]byte, n)
switch v := data.(type) {
case *bool:
if *v {
bs[0] = 1
} else {
bs[0] = 0
}
case bool:
if v {
bs[0] = 1
} else {
bs[0] = 0
}
case []bool:
for i, x := range v {
if x {
bs[i] = 1
} else {
bs[i] = 0
}
}
case *int8:
bs[0] = byte(*v)
case int8:
bs[0] = byte(v)
case []int8:
for i, x := range v {
bs[i] = byte(x)
}
case *uint8:
bs[0] = *v
case uint8:
bs[0] = v
case []uint8:
bs = v
case *int16:
order.PutUint16(bs, u16(*v))
case int16:
order.PutUint16(bs, u16(v))
case []int16:
for i, x := range v {
order.PutUint16(bs[2*i:], u16(x))
}
case *u16:
order.PutUint16(bs, *v)
case u16:
order.PutUint16(bs, v)
case []u16:
for i, x := range v {
order.PutUint16(bs[2*i:], x)
}
case *int32:
order.PutUint32(bs, u32(*v))
case int32:
order.PutUint32(bs, u32(v))
case []int32:
for i, x := range v {
order.PutUint32(bs[4*i:], u32(x))
}
case *u32:
order.PutUint32(bs, *v)
case u32:
order.PutUint32(bs, v)
case []u32:
for i, x := range v {
order.PutUint32(bs[4*i:], x)
}
case *int64:
order.PutUint64(bs, u64(*v))
case int64:
order.PutUint64(bs, u64(v))
case []int64:
for i, x := range v {
order.PutUint64(bs[8*i:], u64(x))
}
case *u64:
order.PutUint64(bs, *v)
case u64:
order.PutUint64(bs, v)
case []u64:
for i, x := range v {
order.PutUint64(bs[8*i:], x)
}
case *float32:
order.PutUint32(bs, math.Float32bits(*v))
case float32:
order.PutUint32(bs, math.Float32bits(v))
case []float32:
for i, x := range v {
order.PutUint32(bs[4*i:], math.Float32bits(x))
}
case *float64:
order.PutUint64(bs, math.Float64bits(*v))
case float64:
order.PutUint64(bs, math.Float64bits(v))
case []float64:
for i, x := range v {
order.PutUint64(bs[8*i:], math.Float64bits(x))
}
}
_, err := w.Write(bs)
return err
}
// Fallback to reflect-based encoding.
v := reflect.Indirect(reflect.ValueOf(data))
size := dataSize(v)
if size < 0 {
return errors.New("binary.Write: invalid type " + reflect.TypeOf(data).String())
}
buf := make([]byte, size)
e := &encoder{order: order, buf: buf}
e.value(v)
_, err := w.Write(buf)
return err
}
// Size returns how many bytes Write would generate to encode the value v, which
// must be a fixed-size value or a slice of fixed-size values, or a pointer to such data.
// If v is neither of these, Size returns -1.
func Size(v interface{}) int {
return dataSize(reflect.Indirect(reflect.ValueOf(v)))
}
var structSize sync.Map // map[reflect.Type]int
// dataSize returns the number of bytes the actual data represented by v occupies in memory.
// For compound structures, it sums the sizes of the elements. Thus, for instance, for a slice
// it returns the length of the slice times the element size and does not count the memory
// occupied by the header. If the type of v is not acceptable, dataSize returns -1.
func dataSize(v reflect.Value) int {
switch v.Kind() {
case reflect.Slice:
if s := sizeof(v.Type().Elem()); s >= 0 {
return s * v.Len()
}
return -1
case reflect.Struct:
t := v.Type()
if size, ok := structSize.Load(t); ok {
return size.(int)
}
size := sizeof(t)
structSize.Store(t, size)
return size
default:
return sizeof(v.Type())
}
}
// sizeof returns the size >= 0 of variables for the given type or -1 if the type is not acceptable.
func sizeof(t reflect.Type) int {
switch t.Kind() {
case reflect.Array:
if s := sizeof(t.Elem()); s >= 0 {
return s * t.Len()
}
case reflect.Struct:
sum := 0
for i, n := 0, t.NumField(); i < n; i++ {
s := sizeof(t.Field(i).Type)
if s < 0 {
return -1
}
sum += s
}
return sum
case reflect.Bool,
reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128:
return int(t.Size())
}
return -1
}
type coder struct {
order ByteOrder
buf []byte
offset int
}
type decoder coder
type encoder coder
func (d *decoder) bool() bool {
x := d.buf[d.offset]
d.offset++
return x != 0
}
func (e *encoder) bool(x bool) {
if x {
e.buf[e.offset] = 1
} else {
e.buf[e.offset] = 0
}
e.offset++
}
func (d *decoder) uint8() uint8 {
x := d.buf[d.offset]
d.offset++
return x
}
func (e *encoder) uint8(x uint8) {
e.buf[e.offset] = x
e.offset++
}
func (d *decoder) u16() u16 {
x := d.order.Uint16(d.buf[d.offset : d.offset+2])
d.offset += 2
return x
}
func (e *encoder) u16(x u16) {
e.order.PutUint16(e.buf[e.offset:e.offset+2], x)
e.offset += 2
}
func (d *decoder) u32() u32 {
x := d.order.Uint32(d.buf[d.offset : d.offset+4])
d.offset += 4
return x
}
func (e *encoder) u32(x u32) {
e.order.PutUint32(e.buf[e.offset:e.offset+4], x)
e.offset += 4
}
func (d *decoder) u64() u64 {
x := d.order.Uint64(d.buf[d.offset : d.offset+8])
d.offset += 8
return x
}
func (e *encoder) u64(x u64) {
e.order.PutUint64(e.buf[e.offset:e.offset+8], x)
e.offset += 8
}
func (d *decoder) int8() int8 { return int8(d.uint8()) }
func (e *encoder) int8(x int8) { e.uint8(uint8(x)) }
func (d *decoder) int16() int16 { return int16(d.u16()) }
func (e *encoder) int16(x int16) { e.u16(u16(x)) }
func (d *decoder) int32() int32 { return int32(d.u32()) }
func (e *encoder) int32(x int32) { e.u32(u32(x)) }
func (d *decoder) int64() int64 { return int64(d.u64()) }
func (e *encoder) int64(x int64) { e.u64(u64(x)) }
func (d *decoder) value(v reflect.Value) {
switch v.Kind() {
case reflect.Array:
l := v.Len()
for i := 0; i < l; i++ {
d.value(v.Index(i))
}
case reflect.Struct:
t := v.Type()
l := v.NumField()
for i := 0; i < l; i++ {
// Note: Calling v.CanSet() below is an optimization.
// It would be sufficient to check the field name,
// but creating the StructField info for each field is
// costly (run "go test -bench=ReadStruct" and compare
// results when making changes to this code).
if v := v.Field(i); v.CanSet() || t.Field(i).Name != "_" {
d.value(v)
} else {
d.skip(v)
}
}
case reflect.Slice:
l := v.Len()
for i := 0; i < l; i++ {
d.value(v.Index(i))
}
case reflect.Bool:
v.SetBool(d.bool())
case reflect.Int8:
v.SetInt(int64(d.int8()))
case reflect.Int16:
v.SetInt(int64(d.int16()))
case reflect.Int32:
v.SetInt(int64(d.int32()))
case reflect.Int64:
v.SetInt(d.int64())
case reflect.Uint8:
v.SetUint(u64(d.uint8()))
case reflect.Uint16:
v.SetUint(u64(d.u16()))
case reflect.Uint32:
v.SetUint(u64(d.u32()))
case reflect.Uint64:
v.SetUint(d.u64())
case reflect.Float32:
v.SetFloat(float64(math.Float32frombits(d.u32())))
case reflect.Float64:
v.SetFloat(math.Float64frombits(d.u64()))
case reflect.Complex64:
v.SetComplex(complex(
float64(math.Float32frombits(d.u32())),
float64(math.Float32frombits(d.u32())),
))
case reflect.Complex128:
v.SetComplex(complex(
math.Float64frombits(d.u64()),
math.Float64frombits(d.u64()),
))
}
}
func (e *encoder) value(v reflect.Value) {
switch v.Kind() {
case reflect.Array:
l := v.Len()
for i := 0; i < l; i++ {
e.value(v.Index(i))
}
case reflect.Struct:
t := v.Type()
l := v.NumField()
for i := 0; i < l; i++ {
// see comment for corresponding code in decoder.value()
if v := v.Field(i); v.CanSet() || t.Field(i).Name != "_" {
e.value(v)
} else {
e.skip(v)
}
}
case reflect.Slice:
l := v.Len()
for i := 0; i < l; i++ {
e.value(v.Index(i))
}
case reflect.Bool:
e.bool(v.Bool())
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
switch v.Type().Kind() {
case reflect.Int8:
e.int8(int8(v.Int()))
case reflect.Int16:
e.int16(int16(v.Int()))
case reflect.Int32:
e.int32(int32(v.Int()))
case reflect.Int64:
e.int64(v.Int())
}
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
switch v.Type().Kind() {
case reflect.Uint8:
e.uint8(uint8(v.Uint()))
case reflect.Uint16:
e.u16(u16(v.Uint()))
case reflect.Uint32:
e.u32(u32(v.Uint()))
case reflect.Uint64:
e.u64(v.Uint())
}
case reflect.Float32, reflect.Float64:
switch v.Type().Kind() {
case reflect.Float32:
e.u32(math.Float32bits(float32(v.Float())))
case reflect.Float64:
e.u64(math.Float64bits(v.Float()))
}
case reflect.Complex64, reflect.Complex128:
switch v.Type().Kind() {
case reflect.Complex64:
x := v.Complex()
e.u32(math.Float32bits(float32(real(x))))
e.u32(math.Float32bits(float32(imag(x))))
case reflect.Complex128:
x := v.Complex()
e.u64(math.Float64bits(real(x)))
e.u64(math.Float64bits(imag(x)))
}
}
}
func (d *decoder) skip(v reflect.Value) {
d.offset += dataSize(v)
}
func (e *encoder) skip(v reflect.Value) {
n := dataSize(v)
zero := e.buf[e.offset : e.offset+n]
for i := range zero {
zero[i] = 0
}
e.offset += n
}
// intDataSize returns the size of the data required to represent the data when encoded.
// It returns zero if the type cannot be implemented by the fast path in Read or Write.
func intDataSize(data interface{}) int {
switch data := data.(type) {
case bool, int8, uint8, *bool, *int8, *uint8:
return 1
case []bool:
return len(data)
case []int8:
return len(data)
case []uint8:
return len(data)
case int16, u16, *int16, *u16:
return 2
case []int16:
return 2 * len(data)
case []u16:
return 2 * len(data)
case int32, u32, *int32, *u32:
return 4
case []int32:
return 4 * len(data)
case []u32:
return 4 * len(data)
case int64, u64, *int64, *u64:
return 8
case []int64:
return 8 * len(data)
case []u64:
return 8 * len(data)
case float32, *float32:
return 4
case float64, *float64:
return 8
case []float32:
return 4 * len(data)
case []float64:
return 8 * len(data)
}
return 0
}
*/
\ No newline at end of file
// 版权 @2023 凹语言 作者。保留所有权利。
// Equal reports whether a and b
// are the same length and contain the same bytes.
// A nil argument is equivalent to an empty slice.
func Equal(a, b: []byte) => bool {
// Neither cmd/compile nor gccgo allocates for these string conversions.
return string(a) == string(b)
}
// 忽略英文大小写比较
func EqualFold(s, t: []byte) => bool {
if len(s) != len(t) {
return false
}
if len(s) == 0 {
return true
}
for i := 0; i < len(s); i++ {
if toupper(s[i]) != toupper(t[i]) {
return false
}
}
return true
}
func toupper(c: byte) => byte {
if c >= 'a' && c <= 'z' {
return c - 32
}
return c
}
func tolower(c: byte) => byte {
if c >= 'A' && c <= 'Z' {
return c + 32
}
return c
}
\ No newline at end of file
// 版权 @2023 凹语言 作者。保留所有权利。
func TestEqual {
for _, tt := range compareTests {
eql := Equal(tt.a, tt.b)
if eql != (tt.i == 0) {
println(string(tt.a), string(tt.b), eql)
assert(false, `Equal failed`)
}
}
}
func TestEqualFold {
for _, tt := range EqualFoldTests {
if out := EqualFold([]byte(tt.s), []byte(tt.t)); out != tt.out {
println(string(tt.s), string(tt.t))
assert(false, `EqualFold failed`)
}
if out := EqualFold([]byte(tt.t), []byte(tt.s)); out != tt.out {
println(string(tt.s), string(tt.t))
assert(false, `EqualFold failed`)
}
}
}
var EqualFoldTests = []struct {
s, t string
out bool
}{
{"abc", "abc", true},
{"ABcd", "ABcd", true},
{"123abc", "123ABC", true},
{"abc", "xyz", false},
{"abc", "XYZ", false},
{"abcdefghijk", "abcdefghijX", false},
}
var compareTests = []struct {
a, b []byte
i int
}{
{[]byte(""), []byte(""), 0},
{[]byte("a"), []byte(""), 1},
{[]byte(""), []byte("a"), -1},
{[]byte("abc"), []byte("abc"), 0},
{[]byte("abd"), []byte("abc"), 1},
{[]byte("abc"), []byte("abd"), -1},
{[]byte("ab"), []byte("abc"), -1},
{[]byte("abc"), []byte("ab"), 1},
{[]byte("x"), []byte("ab"), 1},
{[]byte("ab"), []byte("x"), -1},
{[]byte("x"), []byte("a"), 1},
{[]byte("b"), []byte("x"), -1},
// test runtime·memeq's chunked implementation
{[]byte("abcdefgh"), []byte("abcdefgh"), 0},
{[]byte("abcdefghi"), []byte("abcdefghi"), 0},
{[]byte("abcdefghi"), []byte("abcdefghj"), -1},
{[]byte("abcdefghj"), []byte("abcdefghi"), 1},
// nil tests
{nil, nil, 0},
{[]byte(""), nil, 0},
{nil, []byte(""), 0},
{[]byte("a"), nil, 1},
{nil, []byte("a"), -1},
}
// 版权 @2023 凹语言 作者。保留所有权利。
func New(text: string) => error {
return &errorString{text}
}
type errorString struct {
s :string
}
func errorString.Error => string {
return this.s
}
// 版权 @2023 凹语言 作者。保留所有权利。
import "fmt"
func TestNewEqual {
// Different allocations should not be equal.
if New("abc") == New("abc") {
assert(false, `New("abc") == New("abc")`)
}
if New("abc") == New("xyz") {
assert(false, `New("abc") == New("xyz")`)
}
// Same allocation should be equal to itself (not crash).
err := New("jkl")
if err != err {
assert(false, `err != err`)
}
}
func TestErrorMethod {
err := New("abc")
if err.Error() != "abc" {
assert(false, `New("abc").Error() = "` + err.Error() + `", want "abc"`)
}
}
func ExampleNew() {
err := New("emit macho dwarf: elf header corrupted")
if err != nil {
fmt.Println(err)
}
// Output:
// emit macho dwarf: elf header corrupted
}
// 版权 @2019 凹语言 作者。保留所有权利。
#wa:build !fmt_tag
func Println(a: ...interface{}) {
for i, v := range a {
if i > 0 {
print(" ")
}
switch v:= v.(type) {
case int:
print(v)
case string:
print(v)
case error:
print(v.Error())
}
}
println()
}
// 版权 @2023 凹语言 作者。保留所有权利。
#wa:build fmt_tag
func Println(x: int) {
println("fmt_tag:", x)
}
// 版权 @2023 凹语言 作者。保留所有权利。
func TestOK_assert {
ok := true
assert(ok)
assert(true, "message")
}
func TestOK_output {
println("abc 123")
// Output:
// abc 123
}
\ No newline at end of file
// 版权 @2023 凹语言 作者。保留所有权利。
import (
"errors"
//"image"
//"image/color"
//"io"
)
// ErrUnsupported means that the input BMP image uses a valid but unsupported
// feature.
var ErrUnsupported = errors.New("bmp: unsupported BMP image")
func readUint16(b: []byte) => uint16 {
return uint16(b[0]) | uint16(b[1])<<8
}
func readUint32(b: []byte) => uint32 {
return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
}
/*
// decodeRGB reads a 24 bit-per-pixel BMP image from r.
// If topDown is false, the image rows will be read bottom-up.
func decodeRGB(r: io.Reader, c: image.Config, topDown: bool) => (m: image.Image, err: error) {
rgba := image.NewRGBA(image.Rect(0, 0, c.Width, c.Height))
if c.Width == 0 || c.Height == 0 {
return rgba, nil
}
// There are 3 bytes per pixel, and each row is 4-byte aligned.
b := make([]byte, (3*c.Width+3)&^3)
y0, y1, yDelta := c.Height-1, -1, -1
if topDown {
y0, y1, yDelta = 0, c.Height, +1
}
for y := y0; y != y1; y += yDelta {
if _, err := io.ReadFull(r, b); err != nil {
return nil, err
}
p := rgba.Pix[y*rgba.Stride : y*rgba.Stride+c.Width*4]
for i, j := 0, 0; i < len(p); i, j = i+4, j+3 {
// BMP images are stored in BGR order rather than RGB order.
p[i+0] = b[j+2]
p[i+1] = b[j+1]
p[i+2] = b[j+0]
p[i+3] = 0xFF
}
}
return rgba, nil
}
// decodePaletted reads an 8 bit-per-pixel BMP image from r.
// If topDown is false, the image rows will be read bottom-up.
func decodePaletted(r: io.Reader, c: image.Config, topDown: bool) => (m: image.Image, err: error) {
paletted := image.NewPaletted(image.Rect(0, 0, c.Width, c.Height), c.ColorModel.(color.Palette))
if c.Width == 0 || c.Height == 0 {
return paletted, nil
}
var tmp [4]byte
y0, y1, yDelta := c.Height-1, -1, -1
if topDown {
y0, y1, yDelta = 0, c.Height, +1
}
for y := y0; y != y1; y += yDelta {
p := paletted.Pix[y*paletted.Stride : y*paletted.Stride+c.Width]
if _, err := io.ReadFull(r, p); err != nil {
return nil, err
}
// Each row is 4-byte aligned.
if c.Width%4 != 0 {
_, err := io.ReadFull(r, tmp[:4-c.Width%4])
if err != nil {
return nil, err
}
}
}
return paletted, nil
}
// decodeNRGBA reads a 32 bit-per-pixel BMP image from r.
// If topDown is false, the image rows will be read bottom-up.
func decodeNRGBA(r: io.Reader, c: image.Config, topDown, allowAlpha: bool) => (image.Image, error) {
rgba := image.NewNRGBA(image.Rect(0, 0, c.Width, c.Height))
if c.Width == 0 || c.Height == 0 {
return rgba, nil
}
y0, y1, yDelta := c.Height-1, -1, -1
if topDown {
y0, y1, yDelta = 0, c.Height, +1
}
for y := y0; y != y1; y += yDelta {
p := rgba.Pix[y*rgba.Stride : y*rgba.Stride+c.Width*4]
if _, err := io.ReadFull(r, p); err != nil {
return nil, err
}
for i := 0; i < len(p); i += 4 {
// BMP images are stored in BGRA order rather than RGBA order.
p[i+0], p[i+2] = p[i+2], p[i+0]
if !allowAlpha {
p[i+3] = 0xFF
}
}
}
return rgba, nil
}
// Decode reads a BMP image from r and returns it as an image.Image.
// Limitation: The file must be 8, 24 or 32 bits per pixel.
func Decode(r io.Reader) (image.Image, error) {
c, bpp, topDown, allowAlpha, err := decodeConfig(r)
if err != nil {
return nil, err
}
switch bpp {
case 8:
return decodePaletted(r, c, topDown)
case 24:
return decodeRGB(r, c, topDown)
case 32:
return decodeNRGBA(r, c, topDown, allowAlpha)
}
panic("unreachable")
}
// DecodeConfig returns the color model and dimensions of a BMP image without
// decoding the entire image.
// Limitation: The file must be 8, 24 or 32 bits per pixel.
func DecodeConfig(r io.Reader) (image.Config, error) {
config, _, _, _, err := decodeConfig(r)
return config, err
}
func decodeConfig(r io.Reader) (config image.Config, bitsPerPixel int, topDown bool, allowAlpha bool, err error) {
// We only support those BMP images with one of the following DIB headers:
// - BITMAPINFOHEADER (40 bytes)
// - BITMAPV4HEADER (108 bytes)
// - BITMAPV5HEADER (124 bytes)
const (
fileHeaderLen = 14
infoHeaderLen = 40
v4InfoHeaderLen = 108
v5InfoHeaderLen = 124
)
var b [1024]byte
if _, err := io.ReadFull(r, b[:fileHeaderLen+4]); err != nil {
if err == io.EOF {
err = io.ErrUnexpectedEOF
}
return image.Config{}, 0, false, false, err
}
if string(b[:2]) != "BM" {
return image.Config{}, 0, false, false, errors.New("bmp: invalid format")
}
offset := readUint32(b[10:14])
infoLen := readUint32(b[14:18])
if infoLen != infoHeaderLen && infoLen != v4InfoHeaderLen && infoLen != v5InfoHeaderLen {
return image.Config{}, 0, false, false, ErrUnsupported
}
if _, err := io.ReadFull(r, b[fileHeaderLen+4:fileHeaderLen+infoLen]); err != nil {
if err == io.EOF {
err = io.ErrUnexpectedEOF
}
return image.Config{}, 0, false, false, err
}
width := int(int32(readUint32(b[18:22])))
height := int(int32(readUint32(b[22:26])))
if height < 0 {
height, topDown = -height, true
}
if width < 0 || height < 0 {
return image.Config{}, 0, false, false, ErrUnsupported
}
// We only support 1 plane and 8, 24 or 32 bits per pixel and no
// compression.
planes, bpp, compression := readUint16(b[26:28]), readUint16(b[28:30]), readUint32(b[30:34])
// if compression is set to BI_BITFIELDS, but the bitmask is set to the default bitmask
// that would be used if compression was set to 0, we can continue as if compression was 0
if compression == 3 && infoLen > infoHeaderLen &&
readUint32(b[54:58]) == 0xff0000 && readUint32(b[58:62]) == 0xff00 &&
readUint32(b[62:66]) == 0xff && readUint32(b[66:70]) == 0xff000000 {
compression = 0
}
if planes != 1 || compression != 0 {
return image.Config{}, 0, false, false, ErrUnsupported
}
switch bpp {
case 8:
if offset != fileHeaderLen+infoLen+256*4 {
return image.Config{}, 0, false, false, ErrUnsupported
}
_, err = io.ReadFull(r, b[:256*4])
if err != nil {
return image.Config{}, 0, false, false, err
}
pcm := make(color.Palette, 256)
for i := range pcm {
// BMP images are stored in BGR order rather than RGB order.
// Every 4th byte is padding.
pcm[i] = color.RGBA{b[4*i+2], b[4*i+1], b[4*i+0], 0xFF}
}
return image.Config{ColorModel: pcm, Width: width, Height: height}, 8, topDown, false, nil
case 24:
if offset != fileHeaderLen+infoLen {
return image.Config{}, 0, false, false, ErrUnsupported
}
return image.Config{ColorModel: color.RGBAModel, Width: width, Height: height}, 24, topDown, false, nil
case 32:
if offset != fileHeaderLen+infoLen {
return image.Config{}, 0, false, false, ErrUnsupported
}
// 32 bits per pixel is possibly RGBX (X is padding) or RGBA (A is
// alpha transparency). However, for BMP images, "Alpha is a
// poorly-documented and inconsistently-used feature" says
// https://source.chromium.org/chromium/chromium/src/+/bc0a792d7ebc587190d1a62ccddba10abeea274b:third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_reader.cc;l=621
//
// That goes on to say "BITMAPV3HEADER+ have an alpha bitmask in the
// info header... so we respect it at all times... [For earlier
// (smaller) headers we] ignore alpha in Windows V3 BMPs except inside
// ICO files".
//
// "Ignore" means to always set alpha to 0xFF (fully opaque):
// https://source.chromium.org/chromium/chromium/src/+/bc0a792d7ebc587190d1a62ccddba10abeea274b:third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_reader.h;l=272
//
// Confusingly, "Windows V3" does not correspond to BITMAPV3HEADER, but
// instead corresponds to the earlier (smaller) BITMAPINFOHEADER:
// https://source.chromium.org/chromium/chromium/src/+/bc0a792d7ebc587190d1a62ccddba10abeea274b:third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_reader.cc;l=258
//
// This Go package does not support ICO files and the (infoLen >
// infoHeaderLen) condition distinguishes BITMAPINFOHEADER (40 bytes)
// vs later (larger) headers.
allowAlpha = infoLen > infoHeaderLen
return image.Config{ColorModel: color.RGBAModel, Width: width, Height: height}, 32, topDown, allowAlpha, nil
}
return image.Config{}, 0, false, false, ErrUnsupported
}
*/
\ No newline at end of file
// 版权 @2023 凹语言 作者。保留所有权利。
// Color can convert itself to alpha-premultiplied 16-bits per channel RGBA.
// The conversion may be lossy.
type Color interface {
// RGBA returns the alpha-premultiplied red, green, blue and alpha values
// for the color. Each value ranges within [0, 0xffff], but is represented
// by a u32 so that multiplying by a blend factor up to 0xffff will not
// overflow.
//
// An alpha-premultiplied color component c has been scaled by alpha (a),
// so has valid values 0 <= c <= a.
RGBA() => (r, g, b, a: u32)
}
// RGBA represents a traditional 32-bit alpha-premultiplied color, having 8
// bits for each of red, green, blue and alpha.
//
// An alpha-premultiplied color component C has been scaled by alpha (A), so
// has valid values 0 <= C <= A.
type RGBA struct {
R, G, B, A :u8
}
func RGBA.RGBA => (r, g, b, a :u32) {
r = u32(this.R)
r |= r << 8
g = u32(this.G)
g |= g << 8
b = u32(this.B)
b |= b << 8
a = u32(this.A)
a |= a << 8
return
}
// RGBA64 represents a 64-bit alpha-premultiplied color, having 16 bits for
// each of red, green, blue and alpha.
//
// An alpha-premultiplied color component C has been scaled by alpha (A), so
// has valid values 0 <= C <= A.
type RGBA64 struct {
R, G, B, A :u16
}
func RGBA64.RGBA => (r, g, b, a: u32) {
return u32(this.R), u32(this.G), u32(this.B), u32(this.A)
}
// NRGBA represents a non-alpha-premultiplied 32-bit color.
type NRGBA struct {
R, G, B, A :u8
}
func NRGBA.RGBA => (r, g, b, a :u32) {
r = u32(this.R)
r |= r << 8
r *= u32(this.A)
r /= 0xff
g = u32(this.G)
g |= g << 8
g *= u32(this.A)
g /= 0xff
b = u32(this.B)
b |= b << 8
b *= u32(this.A)
b /= 0xff
a = u32(this.A)
a |= a << 8
return
}
// NRGBA64 represents a non-alpha-premultiplied 64-bit color,
// having 16 bits for each of red, green, blue and alpha.
type NRGBA64 struct {
R, G, B, A :u16
}
func NRGBA64.RGBA => (r, g, b, a :u32) {
r = u32(this.R)
r *= u32(this.A)
r /= 0xffff
g = u32(this.G)
g *= u32(this.A)
g /= 0xffff
b = u32(this.B)
b *= u32(this.A)
b /= 0xffff
a = u32(this.A)
return
}
// Alpha represents an 8-bit alpha color.
type Alpha struct {
A :u8
}
func Alpha.RGBA => (r, g, b, a :u32) {
a = u32(this.A)
a |= a << 8
return a, a, a, a
}
// Alpha16 represents a 16-bit alpha color.
type Alpha16 struct {
A :u16
}
func Alpha16.RGBA => (r, g, b, a :u32) {
a = u32(this.A)
return a, a, a, a
}
// Gray represents an 8-bit grayscale color.
type Gray struct {
Y :u8
}
func Gray.RGBA => (r, g, b, a :u32) {
y := u32(this.Y)
y |= y << 8
return y, y, y, 0xffff
}
// Gray16 represents a 16-bit grayscale color.
type Gray16 struct {
Y :u16
}
func Gray16.RGBA => (r, g, b, a :u32) {
y := u32(this.Y)
return y, y, y, 0xffff
}
// Model can convert any Color to one from its own color model. The conversion
// may be lossy.
type Model interface {
Convert(c: Color) => Color
}
// ModelFunc returns a Model that invokes f to implement the conversion.
func ModelFunc(f: func(c: Color) => Color) => Model {
// Note: using *modelFunc as the implementation
// means that callers can still use comparisons
// like m == RGBAModel. This is not possible if
// we use the func value directly, because funcs
// are no longer comparable.
return &modelFunc{f}
}
type modelFunc struct {
f: func(Color) Color
}
func modelFunc.Convert(c: Color) => Color {
return this.f(c)
}
// Models for the standard color types.
var (
RGBAModel : Model = ModelFunc(rgbaModel)
RGBA64Model : Model = ModelFunc(rgba64Model)
NRGBAModel : Model = ModelFunc(nrgbaModel)
NRGBA64Model : Model = ModelFunc(nrgba64Model)
AlphaModel : Model = ModelFunc(alphaModel)
Alpha16Model : Model = ModelFunc(alpha16Model)
GrayModel : Model = ModelFunc(grayModel)
Gray16Model : Model = ModelFunc(gray16Model)
)
func rgbaModel(c: Color) => Color {
if _, ok := c.(*RGBA); ok {
return c
}
r, g, b, a := c.RGBA()
return &RGBA{u8(r >> 8), u8(g >> 8), u8(b >> 8), u8(a >> 8)}
}
func rgba64Model(c: Color) => Color {
if _, ok := c.(*RGBA64); ok {
return c
}
r, g, b, a := c.RGBA()
return &RGBA64{u16(r), u16(g), u16(b), u16(a)}
}
func nrgbaModel(c: Color) => Color {
if _, ok := c.(*NRGBA); ok {
return c
}
r, g, b, a := c.RGBA()
if a == 0xffff {
return &NRGBA{u8(r >> 8), u8(g >> 8), u8(b >> 8), 0xff}
}
if a == 0 {
return &NRGBA{0, 0, 0, 0}
}
// Since Color.RGBA returns an alpha-premultiplied color, we should have r <= a && g <= a && b <= a.
r = (r * 0xffff) / a
g = (g * 0xffff) / a
b = (b * 0xffff) / a
return &NRGBA{u8(r >> 8), u8(g >> 8), u8(b >> 8), u8(a >> 8)}
}
func nrgba64Model(c: Color) => Color {
if _, ok := c.(*NRGBA64); ok {
return c
}
r, g, b, a := c.RGBA()
if a == 0xffff {
return &NRGBA64{u16(r), u16(g), u16(b), 0xffff}
}
if a == 0 {
return &NRGBA64{0, 0, 0, 0}
}
// Since Color.RGBA returns an alpha-premultiplied color, we should have r <= a && g <= a && b <= a.
r = (r * 0xffff) / a
g = (g * 0xffff) / a
b = (b * 0xffff) / a
return &NRGBA64{u16(r), u16(g), u16(b), u16(a)}
}
func alphaModel(c: Color) => Color {
if _, ok := c.(*Alpha); ok {
return c
}
_, _, _, a := c.RGBA()
return &Alpha{u8(a >> 8)}
}
func alpha16Model(c: Color) => Color {
if _, ok := c.(*Alpha16); ok {
return c
}
_, _, _, a := c.RGBA()
return &Alpha16{u16(a)}
}
func grayModel(c: Color) => Color {
if _, ok := c.(*Gray); ok {
return c
}
r, g, b, _ := c.RGBA()
// These coefficients (the fractions 0.299, 0.587 and 0.114) are the same
// as those given by the JFIF specification and used by func RGBToYCbCr in
// ycbcr.go.
//
// Note that 19595 + 38470 + 7471 equals 65536.
//
// The 24 is 16 + 8. The 16 is the same as used in RGBToYCbCr. The 8 is
// because the return value is 8 bit color, not 16 bit color.
y := (19595*r + 38470*g + 7471*b + 1<<15) >> 24
return &Gray{u8(y)}
}
func gray16Model(c: Color) => Color {
if _, ok := c.(*Gray16); ok {
return c
}
r, g, b, _ := c.RGBA()
// These coefficients (the fractions 0.299, 0.587 and 0.114) are the same
// as those given by the JFIF specification and used by func RGBToYCbCr in
// ycbcr.go.
//
// Note that 19595 + 38470 + 7471 equals 65536.
y := (19595*r + 38470*g + 7471*b + 1<<15) >> 16
return &Gray16{u16(y)}
}
// Palette is a palette of colors.
type Palette: []Color
// Convert returns the palette color closest to c in Euclidean R,G,B space.
func Palette.Convert(c: Color) => Color {
if len(*this) == 0 {
return nil
}
return (*this)[this.Index(c)]
}
// Index returns the index of the palette color closest to c in Euclidean
// R,G,B,A space.
func Palette.Index(c: Color) => int {
// A batch version of this computation is in image/draw/draw.go.
cr, cg, cb, ca := c.RGBA()
ret, bestSum := 0, u32(1<<32-1)
for i, v := range *this {
vr, vg, vb, va := v.RGBA()
sum := sqDiff(cr, vr) + sqDiff(cg, vg) + sqDiff(cb, vb) + sqDiff(ca, va)
if sum < bestSum {
if sum == 0 {
return i
}
ret, bestSum = i, sum
}
}
return ret
}
// sqDiff returns the squared-difference of x and y, shifted by 2 so that
// adding four of those won't overflow a u32.
//
// x and y are both assumed to be in the range [0, 0xffff].
func sqDiff(x, y: u32) => u32 {
// The canonical code of this function looks as follows:
//
// var d u32
// if x > y {
// d = x - y
// } else {
// d = y - x
// }
// return (d * d) >> 2
//
// Language spec guarantees the following properties of unsigned integer
// values operations with respect to overflow/wrap around:
//
// > For unsigned integer values, the operations +, -, *, and << are
// > computed modulo 2n, where n is the bit width of the unsigned
// > integer's type. Loosely speaking, these unsigned integer operations
// > discard high bits upon overflow, and programs may rely on ``wrap
// > around''.
//
// Considering these properties and the fact that this function is
// called in the hot paths (x,y loops), it is reduced to the below code
// which is slightly faster. See TestSqDiff for correctness check.
d := x - y
return (d * d) >> 2
}
// Standard colors.
var (
Black = Gray16{0}
White = Gray16{0xffff}
Transparent = Alpha16{0}
Opaque = Alpha16{0xffff}
)
// 版权 @2023 凹语言 作者。保留所有权利。
//go:build ignore
// +build ignore
package main
// This program generates palette.wa. Invoke it as
// go run gen.go -output palette.wa
import (
"bytes"
"flag"
"fmt"
"go/format"
"io"
"log"
"os"
)
var filename = flag.String("output", "palette.wa", "output file name")
func main() {
flag.Parse()
var buf bytes.Buffer
fmt.Fprintln(&buf, `// 版权 @2023 凹语言 作者。保留所有权利。`)
fmt.Fprintln(&buf)
fmt.Fprintln(&buf, "// 由 go run gen.go -output palette.wa 命令自动生成; 不要手工修改")
fmt.Fprintln(&buf)
fmt.Fprintln(&buf, `import "image/color"`)
fmt.Fprintln(&buf)
printPlan9(&buf)
printWebSafe(&buf)
data, err := format.Source(buf.Bytes())
if err != nil {
log.Fatal(err)
}
err = os.WriteFile(*filename, data, 0644)
if err != nil {
log.Fatal(err)
}
}
func printPlan9(w io.Writer) {
c, lines := [3]int{}, [256]string{}
for r, i := 0, 0; r != 4; r++ {
for v := 0; v != 4; v, i = v+1, i+16 {
for g, j := 0, v-r; g != 4; g++ {
for b := 0; b != 4; b, j = b+1, j+1 {
den := r
if g > den {
den = g
}
if b > den {
den = b
}
if den == 0 {
c[0] = 0x11 * v
c[1] = 0x11 * v
c[2] = 0x11 * v
} else {
num := 17 * (4*den + v)
c[0] = r * num / den
c[1] = g * num / den
c[2] = b * num / den
}
lines[i+(j&0x0f)] =
fmt.Sprintf("\t&color.RGBA{0x%02x, 0x%02x, 0x%02x, 0xff},", c[0], c[1], c[2])
}
}
}
}
fmt.Fprintln(w, "// Plan9 is a 256-color palette that partitions the 24-bit RGB space")
fmt.Fprintln(w, "// into 4×4×4 subdivision, with 4 shades in each subcube. Compared to the")
fmt.Fprintln(w, "// WebSafe, the idea is to reduce the color resolution by dicing the")
fmt.Fprintln(w, "// color cube into fewer cells, and to use the extra space to increase the")
fmt.Fprintln(w, "// intensity resolution. This results in 16 gray shades (4 gray subcubes with")
fmt.Fprintln(w, "// 4 samples in each), 13 shades of each primary and secondary color (3")
fmt.Fprintln(w, "// subcubes with 4 samples plus black) and a reasonable selection of colors")
fmt.Fprintln(w, "// covering the rest of the color cube. The advantage is better representation")
fmt.Fprintln(w, "// of continuous tones.")
fmt.Fprintln(w, "//")
fmt.Fprintln(w, "// This palette was used in the Plan 9 Operating System, described at")
fmt.Fprintln(w, "// https://9p.io/magic/man2html/6/color")
fmt.Fprintln(w, "var Plan9 = []color.Color{")
for _, line := range lines {
fmt.Fprintln(w, line)
}
fmt.Fprintln(w, "}")
fmt.Fprintln(w)
}
func printWebSafe(w io.Writer) {
lines := [6 * 6 * 6]string{}
for r := 0; r < 6; r++ {
for g := 0; g < 6; g++ {
for b := 0; b < 6; b++ {
lines[36*r+6*g+b] =
fmt.Sprintf("\t&color.RGBA{0x%02x, 0x%02x, 0x%02x, 0xff},", 0x33*r, 0x33*g, 0x33*b)
}
}
}
fmt.Fprintln(w, "// WebSafe is a 216-color palette that was popularized by early versions")
fmt.Fprintln(w, "// of Netscape Navigator. It is also known as the Netscape Color Cube.")
fmt.Fprintln(w, "//")
fmt.Fprintln(w, "// See https://en.wikipedia.org/wiki/Web_colors#Web-safe_colors for details.")
fmt.Fprintln(w, "var WebSafe = []color.Color{")
for _, line := range lines {
fmt.Fprintln(w, line)
}
fmt.Fprintln(w, "}")
fmt.Fprintln(w)
}
// 版权 @2023 凹语言 作者。保留所有权利。
// 由 go run gen.go -output palette.wa 命令自动生成; 不要手工修改
import "image/color"
// Plan9 is a 256-color palette that partitions the 24-bit RGB space
// into 4×4×4 subdivision, with 4 shades in each subcube. Compared to the
// WebSafe, the idea is to reduce the color resolution by dicing the
// color cube into fewer cells, and to use the extra space to increase the
// intensity resolution. This results in 16 gray shades (4 gray subcubes with
// 4 samples in each), 13 shades of each primary and secondary color (3
// subcubes with 4 samples plus black) and a reasonable selection of colors
// covering the rest of the color cube. The advantage is better representation
// of continuous tones.
//
// This palette was used in the Plan 9 Operating System, described at
// https://9p.io/magic/man2html/6/color
var Plan9 = []color.Color{
&color.RGBA{0x00, 0x00, 0x00, 0xff},
&color.RGBA{0x00, 0x00, 0x44, 0xff},
&color.RGBA{0x00, 0x00, 0x88, 0xff},
&color.RGBA{0x00, 0x00, 0xcc, 0xff},
&color.RGBA{0x00, 0x44, 0x00, 0xff},
&color.RGBA{0x00, 0x44, 0x44, 0xff},
&color.RGBA{0x00, 0x44, 0x88, 0xff},
&color.RGBA{0x00, 0x44, 0xcc, 0xff},
&color.RGBA{0x00, 0x88, 0x00, 0xff},
&color.RGBA{0x00, 0x88, 0x44, 0xff},
&color.RGBA{0x00, 0x88, 0x88, 0xff},
&color.RGBA{0x00, 0x88, 0xcc, 0xff},
&color.RGBA{0x00, 0xcc, 0x00, 0xff},
&color.RGBA{0x00, 0xcc, 0x44, 0xff},
&color.RGBA{0x00, 0xcc, 0x88, 0xff},
&color.RGBA{0x00, 0xcc, 0xcc, 0xff},
&color.RGBA{0x00, 0xdd, 0xdd, 0xff},
&color.RGBA{0x11, 0x11, 0x11, 0xff},
&color.RGBA{0x00, 0x00, 0x55, 0xff},
&color.RGBA{0x00, 0x00, 0x99, 0xff},
&color.RGBA{0x00, 0x00, 0xdd, 0xff},
&color.RGBA{0x00, 0x55, 0x00, 0xff},
&color.RGBA{0x00, 0x55, 0x55, 0xff},
&color.RGBA{0x00, 0x4c, 0x99, 0xff},
&color.RGBA{0x00, 0x49, 0xdd, 0xff},
&color.RGBA{0x00, 0x99, 0x00, 0xff},
&color.RGBA{0x00, 0x99, 0x4c, 0xff},
&color.RGBA{0x00, 0x99, 0x99, 0xff},
&color.RGBA{0x00, 0x93, 0xdd, 0xff},
&color.RGBA{0x00, 0xdd, 0x00, 0xff},
&color.RGBA{0x00, 0xdd, 0x49, 0xff},
&color.RGBA{0x00, 0xdd, 0x93, 0xff},
&color.RGBA{0x00, 0xee, 0x9e, 0xff},
&color.RGBA{0x00, 0xee, 0xee, 0xff},
&color.RGBA{0x22, 0x22, 0x22, 0xff},
&color.RGBA{0x00, 0x00, 0x66, 0xff},
&color.RGBA{0x00, 0x00, 0xaa, 0xff},
&color.RGBA{0x00, 0x00, 0xee, 0xff},
&color.RGBA{0x00, 0x66, 0x00, 0xff},
&color.RGBA{0x00, 0x66, 0x66, 0xff},
&color.RGBA{0x00, 0x55, 0xaa, 0xff},
&color.RGBA{0x00, 0x4f, 0xee, 0xff},
&color.RGBA{0x00, 0xaa, 0x00, 0xff},
&color.RGBA{0x00, 0xaa, 0x55, 0xff},
&color.RGBA{0x00, 0xaa, 0xaa, 0xff},
&color.RGBA{0x00, 0x9e, 0xee, 0xff},
&color.RGBA{0x00, 0xee, 0x00, 0xff},
&color.RGBA{0x00, 0xee, 0x4f, 0xff},
&color.RGBA{0x00, 0xff, 0x55, 0xff},
&color.RGBA{0x00, 0xff, 0xaa, 0xff},
&color.RGBA{0x00, 0xff, 0xff, 0xff},
&color.RGBA{0x33, 0x33, 0x33, 0xff},
&color.RGBA{0x00, 0x00, 0x77, 0xff},
&color.RGBA{0x00, 0x00, 0xbb, 0xff},
&color.RGBA{0x00, 0x00, 0xff, 0xff},
&color.RGBA{0x00, 0x77, 0x00, 0xff},
&color.RGBA{0x00, 0x77, 0x77, 0xff},
&color.RGBA{0x00, 0x5d, 0xbb, 0xff},
&color.RGBA{0x00, 0x55, 0xff, 0xff},
&color.RGBA{0x00, 0xbb, 0x00, 0xff},
&color.RGBA{0x00, 0xbb, 0x5d, 0xff},
&color.RGBA{0x00, 0xbb, 0xbb, 0xff},
&color.RGBA{0x00, 0xaa, 0xff, 0xff},
&color.RGBA{0x00, 0xff, 0x00, 0xff},
&color.RGBA{0x44, 0x00, 0x44, 0xff},
&color.RGBA{0x44, 0x00, 0x88, 0xff},
&color.RGBA{0x44, 0x00, 0xcc, 0xff},
&color.RGBA{0x44, 0x44, 0x00, 0xff},
&color.RGBA{0x44, 0x44, 0x44, 0xff},
&color.RGBA{0x44, 0x44, 0x88, 0xff},
&color.RGBA{0x44, 0x44, 0xcc, 0xff},
&color.RGBA{0x44, 0x88, 0x00, 0xff},
&color.RGBA{0x44, 0x88, 0x44, 0xff},
&color.RGBA{0x44, 0x88, 0x88, 0xff},
&color.RGBA{0x44, 0x88, 0xcc, 0xff},
&color.RGBA{0x44, 0xcc, 0x00, 0xff},
&color.RGBA{0x44, 0xcc, 0x44, 0xff},
&color.RGBA{0x44, 0xcc, 0x88, 0xff},
&color.RGBA{0x44, 0xcc, 0xcc, 0xff},
&color.RGBA{0x44, 0x00, 0x00, 0xff},
&color.RGBA{0x55, 0x00, 0x00, 0xff},
&color.RGBA{0x55, 0x00, 0x55, 0xff},
&color.RGBA{0x4c, 0x00, 0x99, 0xff},
&color.RGBA{0x49, 0x00, 0xdd, 0xff},
&color.RGBA{0x55, 0x55, 0x00, 0xff},
&color.RGBA{0x55, 0x55, 0x55, 0xff},
&color.RGBA{0x4c, 0x4c, 0x99, 0xff},
&color.RGBA{0x49, 0x49, 0xdd, 0xff},
&color.RGBA{0x4c, 0x99, 0x00, 0xff},
&color.RGBA{0x4c, 0x99, 0x4c, 0xff},
&color.RGBA{0x4c, 0x99, 0x99, 0xff},
&color.RGBA{0x49, 0x93, 0xdd, 0xff},
&color.RGBA{0x49, 0xdd, 0x00, 0xff},
&color.RGBA{0x49, 0xdd, 0x49, 0xff},
&color.RGBA{0x49, 0xdd, 0x93, 0xff},
&color.RGBA{0x49, 0xdd, 0xdd, 0xff},
&color.RGBA{0x4f, 0xee, 0xee, 0xff},
&color.RGBA{0x66, 0x00, 0x00, 0xff},
&color.RGBA{0x66, 0x00, 0x66, 0xff},
&color.RGBA{0x55, 0x00, 0xaa, 0xff},
&color.RGBA{0x4f, 0x00, 0xee, 0xff},
&color.RGBA{0x66, 0x66, 0x00, 0xff},
&color.RGBA{0x66, 0x66, 0x66, 0xff},
&color.RGBA{0x55, 0x55, 0xaa, 0xff},
&color.RGBA{0x4f, 0x4f, 0xee, 0xff},
&color.RGBA{0x55, 0xaa, 0x00, 0xff},
&color.RGBA{0x55, 0xaa, 0x55, 0xff},
&color.RGBA{0x55, 0xaa, 0xaa, 0xff},
&color.RGBA{0x4f, 0x9e, 0xee, 0xff},
&color.RGBA{0x4f, 0xee, 0x00, 0xff},
&color.RGBA{0x4f, 0xee, 0x4f, 0xff},
&color.RGBA{0x4f, 0xee, 0x9e, 0xff},
&color.RGBA{0x55, 0xff, 0xaa, 0xff},
&color.RGBA{0x55, 0xff, 0xff, 0xff},
&color.RGBA{0x77, 0x00, 0x00, 0xff},
&color.RGBA{0x77, 0x00, 0x77, 0xff},
&color.RGBA{0x5d, 0x00, 0xbb, 0xff},
&color.RGBA{0x55, 0x00, 0xff, 0xff},
&color.RGBA{0x77, 0x77, 0x00, 0xff},
&color.RGBA{0x77, 0x77, 0x77, 0xff},
&color.RGBA{0x5d, 0x5d, 0xbb, 0xff},
&color.RGBA{0x55, 0x55, 0xff, 0xff},
&color.RGBA{0x5d, 0xbb, 0x00, 0xff},
&color.RGBA{0x5d, 0xbb, 0x5d, 0xff},
&color.RGBA{0x5d, 0xbb, 0xbb, 0xff},
&color.RGBA{0x55, 0xaa, 0xff, 0xff},
&color.RGBA{0x55, 0xff, 0x00, 0xff},
&color.RGBA{0x55, 0xff, 0x55, 0xff},
&color.RGBA{0x88, 0x00, 0x88, 0xff},
&color.RGBA{0x88, 0x00, 0xcc, 0xff},
&color.RGBA{0x88, 0x44, 0x00, 0xff},
&color.RGBA{0x88, 0x44, 0x44, 0xff},
&color.RGBA{0x88, 0x44, 0x88, 0xff},
&color.RGBA{0x88, 0x44, 0xcc, 0xff},
&color.RGBA{0x88, 0x88, 0x00, 0xff},
&color.RGBA{0x88, 0x88, 0x44, 0xff},
&color.RGBA{0x88, 0x88, 0x88, 0xff},
&color.RGBA{0x88, 0x88, 0xcc, 0xff},
&color.RGBA{0x88, 0xcc, 0x00, 0xff},
&color.RGBA{0x88, 0xcc, 0x44, 0xff},
&color.RGBA{0x88, 0xcc, 0x88, 0xff},
&color.RGBA{0x88, 0xcc, 0xcc, 0xff},
&color.RGBA{0x88, 0x00, 0x00, 0xff},
&color.RGBA{0x88, 0x00, 0x44, 0xff},
&color.RGBA{0x99, 0x00, 0x4c, 0xff},
&color.RGBA{0x99, 0x00, 0x99, 0xff},
&color.RGBA{0x93, 0x00, 0xdd, 0xff},
&color.RGBA{0x99, 0x4c, 0x00, 0xff},
&color.RGBA{0x99, 0x4c, 0x4c, 0xff},
&color.RGBA{0x99, 0x4c, 0x99, 0xff},
&color.RGBA{0x93, 0x49, 0xdd, 0xff},
&color.RGBA{0x99, 0x99, 0x00, 0xff},
&color.RGBA{0x99, 0x99, 0x4c, 0xff},
&color.RGBA{0x99, 0x99, 0x99, 0xff},
&color.RGBA{0x93, 0x93, 0xdd, 0xff},
&color.RGBA{0x93, 0xdd, 0x00, 0xff},
&color.RGBA{0x93, 0xdd, 0x49, 0xff},
&color.RGBA{0x93, 0xdd, 0x93, 0xff},
&color.RGBA{0x93, 0xdd, 0xdd, 0xff},
&color.RGBA{0x99, 0x00, 0x00, 0xff},
&color.RGBA{0xaa, 0x00, 0x00, 0xff},
&color.RGBA{0xaa, 0x00, 0x55, 0xff},
&color.RGBA{0xaa, 0x00, 0xaa, 0xff},
&color.RGBA{0x9e, 0x00, 0xee, 0xff},
&color.RGBA{0xaa, 0x55, 0x00, 0xff},
&color.RGBA{0xaa, 0x55, 0x55, 0xff},
&color.RGBA{0xaa, 0x55, 0xaa, 0xff},
&color.RGBA{0x9e, 0x4f, 0xee, 0xff},
&color.RGBA{0xaa, 0xaa, 0x00, 0xff},
&color.RGBA{0xaa, 0xaa, 0x55, 0xff},
&color.RGBA{0xaa, 0xaa, 0xaa, 0xff},
&color.RGBA{0x9e, 0x9e, 0xee, 0xff},
&color.RGBA{0x9e, 0xee, 0x00, 0xff},
&color.RGBA{0x9e, 0xee, 0x4f, 0xff},
&color.RGBA{0x9e, 0xee, 0x9e, 0xff},
&color.RGBA{0x9e, 0xee, 0xee, 0xff},
&color.RGBA{0xaa, 0xff, 0xff, 0xff},
&color.RGBA{0xbb, 0x00, 0x00, 0xff},
&color.RGBA{0xbb, 0x00, 0x5d, 0xff},
&color.RGBA{0xbb, 0x00, 0xbb, 0xff},
&color.RGBA{0xaa, 0x00, 0xff, 0xff},
&color.RGBA{0xbb, 0x5d, 0x00, 0xff},
&color.RGBA{0xbb, 0x5d, 0x5d, 0xff},
&color.RGBA{0xbb, 0x5d, 0xbb, 0xff},
&color.RGBA{0xaa, 0x55, 0xff, 0xff},
&color.RGBA{0xbb, 0xbb, 0x00, 0xff},
&color.RGBA{0xbb, 0xbb, 0x5d, 0xff},
&color.RGBA{0xbb, 0xbb, 0xbb, 0xff},
&color.RGBA{0xaa, 0xaa, 0xff, 0xff},
&color.RGBA{0xaa, 0xff, 0x00, 0xff},
&color.RGBA{0xaa, 0xff, 0x55, 0xff},
&color.RGBA{0xaa, 0xff, 0xaa, 0xff},
&color.RGBA{0xcc, 0x00, 0xcc, 0xff},
&color.RGBA{0xcc, 0x44, 0x00, 0xff},
&color.RGBA{0xcc, 0x44, 0x44, 0xff},
&color.RGBA{0xcc, 0x44, 0x88, 0xff},
&color.RGBA{0xcc, 0x44, 0xcc, 0xff},
&color.RGBA{0xcc, 0x88, 0x00, 0xff},
&color.RGBA{0xcc, 0x88, 0x44, 0xff},
&color.RGBA{0xcc, 0x88, 0x88, 0xff},
&color.RGBA{0xcc, 0x88, 0xcc, 0xff},
&color.RGBA{0xcc, 0xcc, 0x00, 0xff},
&color.RGBA{0xcc, 0xcc, 0x44, 0xff},
&color.RGBA{0xcc, 0xcc, 0x88, 0xff},
&color.RGBA{0xcc, 0xcc, 0xcc, 0xff},
&color.RGBA{0xcc, 0x00, 0x00, 0xff},
&color.RGBA{0xcc, 0x00, 0x44, 0xff},
&color.RGBA{0xcc, 0x00, 0x88, 0xff},
&color.RGBA{0xdd, 0x00, 0x93, 0xff},
&color.RGBA{0xdd, 0x00, 0xdd, 0xff},
&color.RGBA{0xdd, 0x49, 0x00, 0xff},
&color.RGBA{0xdd, 0x49, 0x49, 0xff},
&color.RGBA{0xdd, 0x49, 0x93, 0xff},
&color.RGBA{0xdd, 0x49, 0xdd, 0xff},
&color.RGBA{0xdd, 0x93, 0x00, 0xff},
&color.RGBA{0xdd, 0x93, 0x49, 0xff},
&color.RGBA{0xdd, 0x93, 0x93, 0xff},
&color.RGBA{0xdd, 0x93, 0xdd, 0xff},
&color.RGBA{0xdd, 0xdd, 0x00, 0xff},
&color.RGBA{0xdd, 0xdd, 0x49, 0xff},
&color.RGBA{0xdd, 0xdd, 0x93, 0xff},
&color.RGBA{0xdd, 0xdd, 0xdd, 0xff},
&color.RGBA{0xdd, 0x00, 0x00, 0xff},
&color.RGBA{0xdd, 0x00, 0x49, 0xff},
&color.RGBA{0xee, 0x00, 0x4f, 0xff},
&color.RGBA{0xee, 0x00, 0x9e, 0xff},
&color.RGBA{0xee, 0x00, 0xee, 0xff},
&color.RGBA{0xee, 0x4f, 0x00, 0xff},
&color.RGBA{0xee, 0x4f, 0x4f, 0xff},
&color.RGBA{0xee, 0x4f, 0x9e, 0xff},
&color.RGBA{0xee, 0x4f, 0xee, 0xff},
&color.RGBA{0xee, 0x9e, 0x00, 0xff},
&color.RGBA{0xee, 0x9e, 0x4f, 0xff},
&color.RGBA{0xee, 0x9e, 0x9e, 0xff},
&color.RGBA{0xee, 0x9e, 0xee, 0xff},
&color.RGBA{0xee, 0xee, 0x00, 0xff},
&color.RGBA{0xee, 0xee, 0x4f, 0xff},
&color.RGBA{0xee, 0xee, 0x9e, 0xff},
&color.RGBA{0xee, 0xee, 0xee, 0xff},
&color.RGBA{0xee, 0x00, 0x00, 0xff},
&color.RGBA{0xff, 0x00, 0x00, 0xff},
&color.RGBA{0xff, 0x00, 0x55, 0xff},
&color.RGBA{0xff, 0x00, 0xaa, 0xff},
&color.RGBA{0xff, 0x00, 0xff, 0xff},
&color.RGBA{0xff, 0x55, 0x00, 0xff},
&color.RGBA{0xff, 0x55, 0x55, 0xff},
&color.RGBA{0xff, 0x55, 0xaa, 0xff},
&color.RGBA{0xff, 0x55, 0xff, 0xff},
&color.RGBA{0xff, 0xaa, 0x00, 0xff},
&color.RGBA{0xff, 0xaa, 0x55, 0xff},
&color.RGBA{0xff, 0xaa, 0xaa, 0xff},
&color.RGBA{0xff, 0xaa, 0xff, 0xff},
&color.RGBA{0xff, 0xff, 0x00, 0xff},
&color.RGBA{0xff, 0xff, 0x55, 0xff},
&color.RGBA{0xff, 0xff, 0xaa, 0xff},
&color.RGBA{0xff, 0xff, 0xff, 0xff},
}
// WebSafe is a 216-color palette that was popularized by early versions
// of Netscape Navigator. It is also known as the Netscape Color Cube.
//
// See https://en.wikipedia.org/wiki/Web_colors#Web-safe_colors for details.
var WebSafe = []color.Color{
&color.RGBA{0x00, 0x00, 0x00, 0xff},
&color.RGBA{0x00, 0x00, 0x33, 0xff},
&color.RGBA{0x00, 0x00, 0x66, 0xff},
&color.RGBA{0x00, 0x00, 0x99, 0xff},
&color.RGBA{0x00, 0x00, 0xcc, 0xff},
&color.RGBA{0x00, 0x00, 0xff, 0xff},
&color.RGBA{0x00, 0x33, 0x00, 0xff},
&color.RGBA{0x00, 0x33, 0x33, 0xff},
&color.RGBA{0x00, 0x33, 0x66, 0xff},
&color.RGBA{0x00, 0x33, 0x99, 0xff},
&color.RGBA{0x00, 0x33, 0xcc, 0xff},
&color.RGBA{0x00, 0x33, 0xff, 0xff},
&color.RGBA{0x00, 0x66, 0x00, 0xff},
&color.RGBA{0x00, 0x66, 0x33, 0xff},
&color.RGBA{0x00, 0x66, 0x66, 0xff},
&color.RGBA{0x00, 0x66, 0x99, 0xff},
&color.RGBA{0x00, 0x66, 0xcc, 0xff},
&color.RGBA{0x00, 0x66, 0xff, 0xff},
&color.RGBA{0x00, 0x99, 0x00, 0xff},
&color.RGBA{0x00, 0x99, 0x33, 0xff},
&color.RGBA{0x00, 0x99, 0x66, 0xff},
&color.RGBA{0x00, 0x99, 0x99, 0xff},
&color.RGBA{0x00, 0x99, 0xcc, 0xff},
&color.RGBA{0x00, 0x99, 0xff, 0xff},
&color.RGBA{0x00, 0xcc, 0x00, 0xff},
&color.RGBA{0x00, 0xcc, 0x33, 0xff},
&color.RGBA{0x00, 0xcc, 0x66, 0xff},
&color.RGBA{0x00, 0xcc, 0x99, 0xff},
&color.RGBA{0x00, 0xcc, 0xcc, 0xff},
&color.RGBA{0x00, 0xcc, 0xff, 0xff},
&color.RGBA{0x00, 0xff, 0x00, 0xff},
&color.RGBA{0x00, 0xff, 0x33, 0xff},
&color.RGBA{0x00, 0xff, 0x66, 0xff},
&color.RGBA{0x00, 0xff, 0x99, 0xff},
&color.RGBA{0x00, 0xff, 0xcc, 0xff},
&color.RGBA{0x00, 0xff, 0xff, 0xff},
&color.RGBA{0x33, 0x00, 0x00, 0xff},
&color.RGBA{0x33, 0x00, 0x33, 0xff},
&color.RGBA{0x33, 0x00, 0x66, 0xff},
&color.RGBA{0x33, 0x00, 0x99, 0xff},
&color.RGBA{0x33, 0x00, 0xcc, 0xff},
&color.RGBA{0x33, 0x00, 0xff, 0xff},
&color.RGBA{0x33, 0x33, 0x00, 0xff},
&color.RGBA{0x33, 0x33, 0x33, 0xff},
&color.RGBA{0x33, 0x33, 0x66, 0xff},
&color.RGBA{0x33, 0x33, 0x99, 0xff},
&color.RGBA{0x33, 0x33, 0xcc, 0xff},
&color.RGBA{0x33, 0x33, 0xff, 0xff},
&color.RGBA{0x33, 0x66, 0x00, 0xff},
&color.RGBA{0x33, 0x66, 0x33, 0xff},
&color.RGBA{0x33, 0x66, 0x66, 0xff},
&color.RGBA{0x33, 0x66, 0x99, 0xff},
&color.RGBA{0x33, 0x66, 0xcc, 0xff},
&color.RGBA{0x33, 0x66, 0xff, 0xff},
&color.RGBA{0x33, 0x99, 0x00, 0xff},
&color.RGBA{0x33, 0x99, 0x33, 0xff},
&color.RGBA{0x33, 0x99, 0x66, 0xff},
&color.RGBA{0x33, 0x99, 0x99, 0xff},
&color.RGBA{0x33, 0x99, 0xcc, 0xff},
&color.RGBA{0x33, 0x99, 0xff, 0xff},
&color.RGBA{0x33, 0xcc, 0x00, 0xff},
&color.RGBA{0x33, 0xcc, 0x33, 0xff},
&color.RGBA{0x33, 0xcc, 0x66, 0xff},
&color.RGBA{0x33, 0xcc, 0x99, 0xff},
&color.RGBA{0x33, 0xcc, 0xcc, 0xff},
&color.RGBA{0x33, 0xcc, 0xff, 0xff},
&color.RGBA{0x33, 0xff, 0x00, 0xff},
&color.RGBA{0x33, 0xff, 0x33, 0xff},
&color.RGBA{0x33, 0xff, 0x66, 0xff},
&color.RGBA{0x33, 0xff, 0x99, 0xff},
&color.RGBA{0x33, 0xff, 0xcc, 0xff},
&color.RGBA{0x33, 0xff, 0xff, 0xff},
&color.RGBA{0x66, 0x00, 0x00, 0xff},
&color.RGBA{0x66, 0x00, 0x33, 0xff},
&color.RGBA{0x66, 0x00, 0x66, 0xff},
&color.RGBA{0x66, 0x00, 0x99, 0xff},
&color.RGBA{0x66, 0x00, 0xcc, 0xff},
&color.RGBA{0x66, 0x00, 0xff, 0xff},
&color.RGBA{0x66, 0x33, 0x00, 0xff},
&color.RGBA{0x66, 0x33, 0x33, 0xff},
&color.RGBA{0x66, 0x33, 0x66, 0xff},
&color.RGBA{0x66, 0x33, 0x99, 0xff},
&color.RGBA{0x66, 0x33, 0xcc, 0xff},
&color.RGBA{0x66, 0x33, 0xff, 0xff},
&color.RGBA{0x66, 0x66, 0x00, 0xff},
&color.RGBA{0x66, 0x66, 0x33, 0xff},
&color.RGBA{0x66, 0x66, 0x66, 0xff},
&color.RGBA{0x66, 0x66, 0x99, 0xff},
&color.RGBA{0x66, 0x66, 0xcc, 0xff},
&color.RGBA{0x66, 0x66, 0xff, 0xff},
&color.RGBA{0x66, 0x99, 0x00, 0xff},
&color.RGBA{0x66, 0x99, 0x33, 0xff},
&color.RGBA{0x66, 0x99, 0x66, 0xff},
&color.RGBA{0x66, 0x99, 0x99, 0xff},
&color.RGBA{0x66, 0x99, 0xcc, 0xff},
&color.RGBA{0x66, 0x99, 0xff, 0xff},
&color.RGBA{0x66, 0xcc, 0x00, 0xff},
&color.RGBA{0x66, 0xcc, 0x33, 0xff},
&color.RGBA{0x66, 0xcc, 0x66, 0xff},
&color.RGBA{0x66, 0xcc, 0x99, 0xff},
&color.RGBA{0x66, 0xcc, 0xcc, 0xff},
&color.RGBA{0x66, 0xcc, 0xff, 0xff},
&color.RGBA{0x66, 0xff, 0x00, 0xff},
&color.RGBA{0x66, 0xff, 0x33, 0xff},
&color.RGBA{0x66, 0xff, 0x66, 0xff},
&color.RGBA{0x66, 0xff, 0x99, 0xff},
&color.RGBA{0x66, 0xff, 0xcc, 0xff},
&color.RGBA{0x66, 0xff, 0xff, 0xff},
&color.RGBA{0x99, 0x00, 0x00, 0xff},
&color.RGBA{0x99, 0x00, 0x33, 0xff},
&color.RGBA{0x99, 0x00, 0x66, 0xff},
&color.RGBA{0x99, 0x00, 0x99, 0xff},
&color.RGBA{0x99, 0x00, 0xcc, 0xff},
&color.RGBA{0x99, 0x00, 0xff, 0xff},
&color.RGBA{0x99, 0x33, 0x00, 0xff},
&color.RGBA{0x99, 0x33, 0x33, 0xff},
&color.RGBA{0x99, 0x33, 0x66, 0xff},
&color.RGBA{0x99, 0x33, 0x99, 0xff},
&color.RGBA{0x99, 0x33, 0xcc, 0xff},
&color.RGBA{0x99, 0x33, 0xff, 0xff},
&color.RGBA{0x99, 0x66, 0x00, 0xff},
&color.RGBA{0x99, 0x66, 0x33, 0xff},
&color.RGBA{0x99, 0x66, 0x66, 0xff},
&color.RGBA{0x99, 0x66, 0x99, 0xff},
&color.RGBA{0x99, 0x66, 0xcc, 0xff},
&color.RGBA{0x99, 0x66, 0xff, 0xff},
&color.RGBA{0x99, 0x99, 0x00, 0xff},
&color.RGBA{0x99, 0x99, 0x33, 0xff},
&color.RGBA{0x99, 0x99, 0x66, 0xff},
&color.RGBA{0x99, 0x99, 0x99, 0xff},
&color.RGBA{0x99, 0x99, 0xcc, 0xff},
&color.RGBA{0x99, 0x99, 0xff, 0xff},
&color.RGBA{0x99, 0xcc, 0x00, 0xff},
&color.RGBA{0x99, 0xcc, 0x33, 0xff},
&color.RGBA{0x99, 0xcc, 0x66, 0xff},
&color.RGBA{0x99, 0xcc, 0x99, 0xff},
&color.RGBA{0x99, 0xcc, 0xcc, 0xff},
&color.RGBA{0x99, 0xcc, 0xff, 0xff},
&color.RGBA{0x99, 0xff, 0x00, 0xff},
&color.RGBA{0x99, 0xff, 0x33, 0xff},
&color.RGBA{0x99, 0xff, 0x66, 0xff},
&color.RGBA{0x99, 0xff, 0x99, 0xff},
&color.RGBA{0x99, 0xff, 0xcc, 0xff},
&color.RGBA{0x99, 0xff, 0xff, 0xff},
&color.RGBA{0xcc, 0x00, 0x00, 0xff},
&color.RGBA{0xcc, 0x00, 0x33, 0xff},
&color.RGBA{0xcc, 0x00, 0x66, 0xff},
&color.RGBA{0xcc, 0x00, 0x99, 0xff},
&color.RGBA{0xcc, 0x00, 0xcc, 0xff},
&color.RGBA{0xcc, 0x00, 0xff, 0xff},
&color.RGBA{0xcc, 0x33, 0x00, 0xff},
&color.RGBA{0xcc, 0x33, 0x33, 0xff},
&color.RGBA{0xcc, 0x33, 0x66, 0xff},
&color.RGBA{0xcc, 0x33, 0x99, 0xff},
&color.RGBA{0xcc, 0x33, 0xcc, 0xff},
&color.RGBA{0xcc, 0x33, 0xff, 0xff},
&color.RGBA{0xcc, 0x66, 0x00, 0xff},
&color.RGBA{0xcc, 0x66, 0x33, 0xff},
&color.RGBA{0xcc, 0x66, 0x66, 0xff},
&color.RGBA{0xcc, 0x66, 0x99, 0xff},
&color.RGBA{0xcc, 0x66, 0xcc, 0xff},
&color.RGBA{0xcc, 0x66, 0xff, 0xff},
&color.RGBA{0xcc, 0x99, 0x00, 0xff},
&color.RGBA{0xcc, 0x99, 0x33, 0xff},
&color.RGBA{0xcc, 0x99, 0x66, 0xff},
&color.RGBA{0xcc, 0x99, 0x99, 0xff},
&color.RGBA{0xcc, 0x99, 0xcc, 0xff},
&color.RGBA{0xcc, 0x99, 0xff, 0xff},
&color.RGBA{0xcc, 0xcc, 0x00, 0xff},
&color.RGBA{0xcc, 0xcc, 0x33, 0xff},
&color.RGBA{0xcc, 0xcc, 0x66, 0xff},
&color.RGBA{0xcc, 0xcc, 0x99, 0xff},
&color.RGBA{0xcc, 0xcc, 0xcc, 0xff},
&color.RGBA{0xcc, 0xcc, 0xff, 0xff},
&color.RGBA{0xcc, 0xff, 0x00, 0xff},
&color.RGBA{0xcc, 0xff, 0x33, 0xff},
&color.RGBA{0xcc, 0xff, 0x66, 0xff},
&color.RGBA{0xcc, 0xff, 0x99, 0xff},
&color.RGBA{0xcc, 0xff, 0xcc, 0xff},
&color.RGBA{0xcc, 0xff, 0xff, 0xff},
&color.RGBA{0xff, 0x00, 0x00, 0xff},
&color.RGBA{0xff, 0x00, 0x33, 0xff},
&color.RGBA{0xff, 0x00, 0x66, 0xff},
&color.RGBA{0xff, 0x00, 0x99, 0xff},
&color.RGBA{0xff, 0x00, 0xcc, 0xff},
&color.RGBA{0xff, 0x00, 0xff, 0xff},
&color.RGBA{0xff, 0x33, 0x00, 0xff},
&color.RGBA{0xff, 0x33, 0x33, 0xff},
&color.RGBA{0xff, 0x33, 0x66, 0xff},
&color.RGBA{0xff, 0x33, 0x99, 0xff},
&color.RGBA{0xff, 0x33, 0xcc, 0xff},
&color.RGBA{0xff, 0x33, 0xff, 0xff},
&color.RGBA{0xff, 0x66, 0x00, 0xff},
&color.RGBA{0xff, 0x66, 0x33, 0xff},
&color.RGBA{0xff, 0x66, 0x66, 0xff},
&color.RGBA{0xff, 0x66, 0x99, 0xff},
&color.RGBA{0xff, 0x66, 0xcc, 0xff},
&color.RGBA{0xff, 0x66, 0xff, 0xff},
&color.RGBA{0xff, 0x99, 0x00, 0xff},
&color.RGBA{0xff, 0x99, 0x33, 0xff},
&color.RGBA{0xff, 0x99, 0x66, 0xff},
&color.RGBA{0xff, 0x99, 0x99, 0xff},
&color.RGBA{0xff, 0x99, 0xcc, 0xff},
&color.RGBA{0xff, 0x99, 0xff, 0xff},
&color.RGBA{0xff, 0xcc, 0x00, 0xff},
&color.RGBA{0xff, 0xcc, 0x33, 0xff},
&color.RGBA{0xff, 0xcc, 0x66, 0xff},
&color.RGBA{0xff, 0xcc, 0x99, 0xff},
&color.RGBA{0xff, 0xcc, 0xcc, 0xff},
&color.RGBA{0xff, 0xcc, 0xff, 0xff},
&color.RGBA{0xff, 0xff, 0x00, 0xff},
&color.RGBA{0xff, 0xff, 0x33, 0xff},
&color.RGBA{0xff, 0xff, 0x66, 0xff},
&color.RGBA{0xff, 0xff, 0x99, 0xff},
&color.RGBA{0xff, 0xff, 0xcc, 0xff},
&color.RGBA{0xff, 0xff, 0xff, 0xff},
}
// 版权 @2023 凹语言 作者。保留所有权利。
import (
//"image/color"
"strconv"
)
// A Point is an X, Y coordinate pair. The axes increase right and down.
type Point struct {
X, Y :int
}
// String returns a string representation of p like "(3,4)".
func Point.String => string {
return "(" + strconv.Itoa(this.X) + "," + strconv.Itoa(this.Y) + ")"
}
// Add returns the vector p+q.
func Point.Add(q :Point) => Point {
return Point{this.X + q.X, this.Y + q.Y}
}
// Sub returns the vector p-q.
func Point.Sub(q: Point) => Point {
return Point{this.X - q.X, this.Y - q.Y}
}
// Mul returns the vector p*k.
func Point.Mul(k: int) => Point {
return Point{this.X * k, this.Y * k}
}
// Div returns the vector p/k.
func Point.Div(k: int) => Point {
return Point{this.X / k, this.Y / k}
}
// In reports whether p is in r.
func Point.In(r: Rectangle) => bool {
return r.Min.X <= this.X && this.X < r.Max.X &&
r.Min.Y <= this.Y && this.Y < r.Max.Y
}
/*
// Mod returns the point q in r such that p.X-q.X is a multiple of r's width
// and p.Y-q.Y is a multiple of r's height.
func (p Point) Mod(r Rectangle) Point {
w, h := r.Dx(), r.Dy()
p = p.Sub(r.Min)
p.X = p.X % w
if p.X < 0 {
p.X += w
}
p.Y = p.Y % h
if p.Y < 0 {
p.Y += h
}
return p.Add(r.Min)
}
// Eq reports whether p and q are equal.
func (p Point) Eq(q Point) bool {
return p == q
}
// ZP is the zero Point.
//
// Deprecated: Use a literal image.Point{} instead.
var ZP Point
// Pt is shorthand for Point{X, Y}.
func Pt(X, Y int) Point {
return Point{X, Y}
}
*/
// A Rectangle contains the points with Min.X <= X < Max.X, Min.Y <= Y < Max.Y.
// It is well-formed if Min.X <= Max.X and likewise for Y. Points are always
// well-formed. A rectangle's methods always return well-formed outputs for
// well-formed inputs.
//
// A Rectangle is also an Image whose bounds are the rectangle itself. At
// returns color.Opaque for points in the rectangle and color.Transparent
// otherwise.
type Rectangle struct {
Min, Max: Point
}
// String returns a string representation of r like "(3,4)-(6,5)".
func Rectangle.String => string {
return this.Min.String() + "-" + this.Max.String()
}
/*
// Dx returns r's width.
func (r Rectangle) Dx() int {
return r.Max.X - r.Min.X
}
// Dy returns r's height.
func (r Rectangle) Dy() int {
return r.Max.Y - r.Min.Y
}
// Size returns r's width and height.
func (r Rectangle) Size() Point {
return Point{
r.Max.X - r.Min.X,
r.Max.Y - r.Min.Y,
}
}
// Add returns the rectangle r translated by p.
func (r Rectangle) Add(p Point) Rectangle {
return Rectangle{
Point{r.Min.X + p.X, r.Min.Y + p.Y},
Point{r.Max.X + p.X, r.Max.Y + p.Y},
}
}
// Sub returns the rectangle r translated by -p.
func (r Rectangle) Sub(p Point) Rectangle {
return Rectangle{
Point{r.Min.X - p.X, r.Min.Y - p.Y},
Point{r.Max.X - p.X, r.Max.Y - p.Y},
}
}
// Inset returns the rectangle r inset by n, which may be negative. If either
// of r's dimensions is less than 2*n then an empty rectangle near the center
// of r will be returned.
func (r Rectangle) Inset(n int) Rectangle {
if r.Dx() < 2*n {
r.Min.X = (r.Min.X + r.Max.X) / 2
r.Max.X = r.Min.X
} else {
r.Min.X += n
r.Max.X -= n
}
if r.Dy() < 2*n {
r.Min.Y = (r.Min.Y + r.Max.Y) / 2
r.Max.Y = r.Min.Y
} else {
r.Min.Y += n
r.Max.Y -= n
}
return r
}
// Intersect returns the largest rectangle contained by both r and s. If the
// two rectangles do not overlap then the zero rectangle will be returned.
func (r Rectangle) Intersect(s Rectangle) Rectangle {
if r.Min.X < s.Min.X {
r.Min.X = s.Min.X
}
if r.Min.Y < s.Min.Y {
r.Min.Y = s.Min.Y
}
if r.Max.X > s.Max.X {
r.Max.X = s.Max.X
}
if r.Max.Y > s.Max.Y {
r.Max.Y = s.Max.Y
}
// Letting r0 and s0 be the values of r and s at the time that the method
// is called, this next line is equivalent to:
//
// if max(r0.Min.X, s0.Min.X) >= min(r0.Max.X, s0.Max.X) || likewiseForY { etc }
if r.Empty() {
return ZR
}
return r
}
// Union returns the smallest rectangle that contains both r and s.
func (r Rectangle) Union(s Rectangle) Rectangle {
if r.Empty() {
return s
}
if s.Empty() {
return r
}
if r.Min.X > s.Min.X {
r.Min.X = s.Min.X
}
if r.Min.Y > s.Min.Y {
r.Min.Y = s.Min.Y
}
if r.Max.X < s.Max.X {
r.Max.X = s.Max.X
}
if r.Max.Y < s.Max.Y {
r.Max.Y = s.Max.Y
}
return r
}
// Empty reports whether the rectangle contains no points.
func (r Rectangle) Empty() bool {
return r.Min.X >= r.Max.X || r.Min.Y >= r.Max.Y
}
// Eq reports whether r and s contain the same set of points. All empty
// rectangles are considered equal.
func (r Rectangle) Eq(s Rectangle) bool {
return r == s || r.Empty() && s.Empty()
}
// Overlaps reports whether r and s have a non-empty intersection.
func (r Rectangle) Overlaps(s Rectangle) bool {
return !r.Empty() && !s.Empty() &&
r.Min.X < s.Max.X && s.Min.X < r.Max.X &&
r.Min.Y < s.Max.Y && s.Min.Y < r.Max.Y
}
// In reports whether every point in r is in s.
func (r Rectangle) In(s Rectangle) bool {
if r.Empty() {
return true
}
// Note that r.Max is an exclusive bound for r, so that r.In(s)
// does not require that r.Max.In(s).
return s.Min.X <= r.Min.X && r.Max.X <= s.Max.X &&
s.Min.Y <= r.Min.Y && r.Max.Y <= s.Max.Y
}
// Canon returns the canonical version of r. The returned rectangle has minimum
// and maximum coordinates swapped if necessary so that it is well-formed.
func (r Rectangle) Canon() Rectangle {
if r.Max.X < r.Min.X {
r.Min.X, r.Max.X = r.Max.X, r.Min.X
}
if r.Max.Y < r.Min.Y {
r.Min.Y, r.Max.Y = r.Max.Y, r.Min.Y
}
return r
}
// At implements the Image interface.
func (r Rectangle) At(x, y int) color.Color {
if (Point{x, y}).In(r) {
return color.Opaque
}
return color.Transparent
}
// RGBA64At implements the RGBA64Image interface.
func (r Rectangle) RGBA64At(x, y int) color.RGBA64 {
if (Point{x, y}).In(r) {
return color.RGBA64{0xffff, 0xffff, 0xffff, 0xffff}
}
return color.RGBA64{}
}
// Bounds implements the Image interface.
func (r Rectangle) Bounds() Rectangle {
return r
}
// ColorModel implements the Image interface.
func (r Rectangle) ColorModel() color.Model {
return color.Alpha16Model
}
// ZR is the zero Rectangle.
//
// Deprecated: Use a literal image.Rectangle{} instead.
var ZR Rectangle
// Rect is shorthand for Rectangle{Pt(x0, y0), Pt(x1, y1)}. The returned
// rectangle has minimum and maximum coordinates swapped if necessary so that
// it is well-formed.
func Rect(x0, y0, x1, y1 int) Rectangle {
if x0 > x1 {
x0, x1 = x1, x0
}
if y0 > y1 {
y0, y1 = y1, y0
}
return Rectangle{Point{x0, y0}, Point{x1, y1}}
}
// mul3NonNeg returns (x * y * z), unless at least one argument is negative or
// if the computation overflows the int type, in which case it returns -1.
func mul3NonNeg(x int, y int, z int) int {
if (x < 0) || (y < 0) || (z < 0) {
return -1
}
hi, lo := bits.Mul64(uint64(x), uint64(y))
if hi != 0 {
return -1
}
hi, lo = bits.Mul64(lo, uint64(z))
if hi != 0 {
return -1
}
a := int(lo)
if (a < 0) || (uint64(a) != lo) {
return -1
}
return a
}
// add2NonNeg returns (x + y), unless at least one argument is negative or if
// the computation overflows the int type, in which case it returns -1.
func add2NonNeg(x int, y int) int {
if (x < 0) || (y < 0) {
return -1
}
a := x + y
if a < 0 {
return -1
}
return a
}
*/
\ No newline at end of file
此差异已折叠。
// 版权 @2019 凹语言 作者。保留所有权利。
import "errors"
// Seek whence values.
const (
SeekStart = 0 // seek relative to the origin of the file
SeekCurrent = 1 // seek relative to the current offset
SeekEnd = 2 // seek relative to the end
)
// ErrShortWrite means that a write accepted fewer bytes than requested
// but failed to return an explicit error.
var ErrShortWrite = errors.New("short write")
// errInvalidWrite means that a write returned an impossible count.
var errInvalidWrite = errors.New("invalid write result")
// ErrShortBuffer means that a read required a longer buffer than was provided.
var ErrShortBuffer = errors.New("short buffer")
// EOF is the error returned by Read when no more input is available.
// (Read must return EOF itself, not an error wrapping EOF,
// because callers will test for EOF using ==.)
// Functions should return EOF only to signal a graceful end of input.
// If the EOF occurs unexpectedly in a structured data stream,
// the appropriate error is either ErrUnexpectedEOF or some other error
// giving more detail.
var EOF = errors.New("EOF")
// ErrUnexpectedEOF means that EOF was encountered in the
// middle of reading a fixed-size block or data structure.
var ErrUnexpectedEOF = errors.New("unexpected EOF")
// ErrNoProgress is returned by some clients of an Reader when
// many calls to Read have failed to return any data or error,
// usually the sign of a broken Reader implementation.
var ErrNoProgress = errors.New("multiple Read calls return no data or error")
// Reader is the interface that wraps the basic Read method.
//
// Read reads up to len(p) bytes into p. It returns the number of bytes
// read (0 <= n <= len(p)) and any error encountered. Even if Read
// returns n < len(p), it may use all of p as scratch space during the call.
// If some data is available but not len(p) bytes, Read conventionally
// returns what is available instead of waiting for more.
//
// When Read encounters an error or end-of-file condition after
// successfully reading n > 0 bytes, it returns the number of
// bytes read. It may return the (non-nil) error from the same call
// or return the error (and n == 0) from a subsequent call.
// An instance of this general case is that a Reader returning
// a non-zero number of bytes at the end of the input stream may
// return either err == EOF or err == nil. The next Read should
// return 0, EOF.
//
// Callers should always process the n > 0 bytes returned before
// considering the error err. Doing so correctly handles I/O errors
// that happen after reading some bytes and also both of the
// allowed EOF behaviors.
//
// Implementations of Read are discouraged from returning a
// zero byte count with a nil error, except when len(p) == 0.
// Callers should treat a return of 0 and nil as indicating that
// nothing happened; in particular it does not indicate EOF.
//
// Implementations must not retain p.
type Reader interface {
Read(p: []byte) => (n: int, err: error)
}
// Writer is the interface that wraps the basic Write method.
//
// Write writes len(p) bytes from p to the underlying data stream.
// It returns the number of bytes written from p (0 <= n <= len(p))
// and any error encountered that caused the write to stop early.
// Write must return a non-nil error if it returns n < len(p).
// Write must not modify the slice data, even temporarily.
//
// Implementations must not retain p.
type Writer interface {
Write(p: []byte) => (n: int, err: error)
}
// Closer is the interface that wraps the basic Close method.
//
// The behavior of Close after the first call is undefined.
// Specific implementations may document their own behavior.
type Closer interface {
Close() => error
}
// Seeker is the interface that wraps the basic Seek method.
//
// Seek sets the offset for the next Read or Write to offset,
// interpreted according to whence:
// SeekStart means relative to the start of the file,
// SeekCurrent means relative to the current offset, and
// SeekEnd means relative to the end.
// Seek returns the new offset relative to the start of the
// file and an error, if any.
//
// Seeking to an offset before the start of the file is an error.
// Seeking to any positive offset is legal, but the behavior of subsequent
// I/O operations on the underlying object is implementation-dependent.
type Seeker interface {
Seek(offset: i64, whence: int) => (i64, error)
}
// ReadWriter is the interface that groups the basic Read and Write methods.
type ReadWriter interface {
Reader
Writer
}
// ReadCloser is the interface that groups the basic Read and Close methods.
type ReadCloser interface {
Reader
Closer
}
// WriteCloser is the interface that groups the basic Write and Close methods.
type WriteCloser interface {
Writer
Closer
}
// ReadWriteCloser is the interface that groups the basic Read, Write and Close methods.
type ReadWriteCloser interface {
Reader
Writer
Closer
}
// ReadSeeker is the interface that groups the basic Read and Seek methods.
type ReadSeeker interface {
Reader
Seeker
}
// ReadSeekCloser is the interface that groups the basic Read, Seek and Close
// methods.
type ReadSeekCloser interface {
Reader
Seeker
Closer
}
// WriteSeeker is the interface that groups the basic Write and Seek methods.
type WriteSeeker interface {
Writer
Seeker
}
// ReadWriteSeeker is the interface that groups the basic Read, Write and Seek methods.
type ReadWriteSeeker interface {
Reader
Writer
Seeker
}
// ReaderFrom is the interface that wraps the ReadFrom method.
//
// ReadFrom reads data from r until EOF or error.
// The return value n is the number of bytes read.
// Any error except EOF encountered during the read is also returned.
//
// The Copy function uses ReaderFrom if available.
type ReaderFrom interface {
ReadFrom(r: Reader) => (n: int64, err: error)
}
// WriterTo is the interface that wraps the WriteTo method.
//
// WriteTo writes data to w until there's no more data to write or
// when an error occurs. The return value n is the number of bytes
// written. Any error encountered during the write is also returned.
//
// The Copy function uses WriterTo if available.
type WriterTo interface {
WriteTo(w: Writer) => (n: i64, err: error)
}
// ReaderAt is the interface that wraps the basic ReadAt method.
//
// ReadAt reads len(p) bytes into p starting at offset off in the
// underlying input source. It returns the number of bytes
// read (0 <= n <= len(p)) and any error encountered.
//
// When ReadAt returns n < len(p), it returns a non-nil error
// explaining why more bytes were not returned. In this respect,
// ReadAt is stricter than Read.
//
// Even if ReadAt returns n < len(p), it may use all of p as scratch
// space during the call. If some data is available but not len(p) bytes,
// ReadAt blocks until either all the data is available or an error occurs.
// In this respect ReadAt is different from Read.
//
// If the n = len(p) bytes returned by ReadAt are at the end of the
// input source, ReadAt may return either err == EOF or err == nil.
//
// If ReadAt is reading from an input source with a seek offset,
// ReadAt should not affect nor be affected by the underlying
// seek offset.
//
// Clients of ReadAt can execute parallel ReadAt calls on the
// same input source.
//
// Implementations must not retain p.
type ReaderAt interface {
ReadAt(p: []byte, off: i64) => (n: int, err: error)
}
// WriterAt is the interface that wraps the basic WriteAt method.
//
// WriteAt writes len(p) bytes from p to the underlying data stream
// at offset off. It returns the number of bytes written from p (0 <= n <= len(p))
// and any error encountered that caused the write to stop early.
// WriteAt must return a non-nil error if it returns n < len(p).
//
// If WriteAt is writing to a destination with a seek offset,
// WriteAt should not affect nor be affected by the underlying
// seek offset.
//
// Clients of WriteAt can execute parallel WriteAt calls on the same
// destination if the ranges do not overlap.
//
// Implementations must not retain p.
type WriterAt interface {
WriteAt(p: []byte, off: i64) => (n: int, err: error)
}
// ByteReader is the interface that wraps the ReadByte method.
//
// ReadByte reads and returns the next byte from the input or
// any error encountered. If ReadByte returns an error, no input
// byte was consumed, and the returned byte value is undefined.
//
// ReadByte provides an efficient interface for byte-at-time
// processing. A Reader that does not implement ByteReader
// can be wrapped using bufio.NewReader to add this method.
type ByteReader interface {
ReadByte() => (byte, error)
}
// ByteScanner is the interface that adds the UnreadByte method to the
// basic ReadByte method.
//
// UnreadByte causes the next call to ReadByte to return the same byte
// as the previous call to ReadByte.
// It may be an error to call UnreadByte twice without an intervening
// call to ReadByte.
type ByteScanner interface {
ByteReader
UnreadByte() => error
}
// ByteWriter is the interface that wraps the WriteByte method.
type ByteWriter interface {
WriteByte(c: byte) => error
}
// RuneReader is the interface that wraps the ReadRune method.
//
// ReadRune reads a single UTF-8 encoded Unicode character
// and returns the rune and its size in bytes. If no character is
// available, err will be set.
type RuneReader interface {
ReadRune() => (r: rune, size: int, err: error)
}
// RuneScanner is the interface that adds the UnreadRune method to the
// basic ReadRune method.
//
// UnreadRune causes the next call to ReadRune to return the same rune
// as the previous call to ReadRune.
// It may be an error to call UnreadRune twice without an intervening
// call to ReadRune.
type RuneScanner interface {
RuneReader
UnreadRune() => error
}
// StringWriter is the interface that wraps the WriteString method.
type StringWriter interface {
WriteString(s: string) => (n: int, err: error)
}
// WriteString writes the contents of the string s to w, which accepts a slice of bytes.
// If w implements StringWriter, its WriteString method is invoked directly.
// Otherwise, w.Write is called exactly once.
func WriteString(w: Writer, s: string) => (n: int, err: error) {
if sw, ok := w.(StringWriter); ok {
return sw.WriteString(s)
}
return w.Write([]byte(s))
}
// ReadAtLeast reads from r into buf until it has read at least min bytes.
// It returns the number of bytes copied and an error if fewer bytes were read.
// The error is EOF only if no bytes were read.
// If an EOF happens after reading fewer than min bytes,
// ReadAtLeast returns ErrUnexpectedEOF.
// If min is greater than the length of buf, ReadAtLeast returns ErrShortBuffer.
// On return, n >= min if and only if err == nil.
// If r returns an error having read at least min bytes, the error is dropped.
func ReadAtLeast(r: Reader, buf: []byte, min: int) => (n: int, err: error) {
if len(buf) < min {
return 0, ErrShortBuffer
}
for n < min && err == nil {
var nn :int
nn, err = r.Read(buf[n:])
n += nn
}
if n >= min {
err = nil
} else if n > 0 && err == EOF {
err = ErrUnexpectedEOF
}
return
}
// ReadFull reads exactly len(buf) bytes from r into buf.
// It returns the number of bytes copied and an error if fewer bytes were read.
// The error is EOF only if no bytes were read.
// If an EOF happens after reading some but not all the bytes,
// ReadFull returns ErrUnexpectedEOF.
// On return, n == len(buf) if and only if err == nil.
// If r returns an error having read at least len(buf) bytes, the error is dropped.
func ReadFull(r: Reader, buf: []byte) => (n: int, err: error) {
return ReadAtLeast(r, buf, len(buf))
}
// CopyN copies n bytes (or until an error) from src to dst.
// It returns the number of bytes copied and the earliest
// error encountered while copying.
// On return, written == n if and only if err == nil.
//
// If dst implements the ReaderFrom interface,
// the copy is implemented using it.
func CopyN(dst: Writer, src: Reader, n: i64) => (written: i64, err: error) {
written, err = Copy(dst, LimitReader(src, n))
if written == n {
return n, nil
}
if written < n && err == nil {
// src stopped early; must have been EOF.
err = EOF
}
return
}
// Copy copies from src to dst until either EOF is reached
// on src or an error occurs. It returns the number of bytes
// copied and the first error encountered while copying, if any.
//
// A successful Copy returns err == nil, not err == EOF.
// Because Copy is defined to read from src until EOF, it does
// not treat an EOF from Read as an error to be reported.
//
// If src implements the WriterTo interface,
// the copy is implemented by calling src.WriteTo(dst).
// Otherwise, if dst implements the ReaderFrom interface,
// the copy is implemented by calling dst.ReadFrom(src).
func Copy(dst: Writer, src: Reader) => (written: i64, err: error) {
return copyBuffer(dst, src, nil)
}
// CopyBuffer is identical to Copy except that it stages through the
// provided buffer (if one is required) rather than allocating a
// temporary one. If buf is nil, one is allocated; otherwise if it has
// zero length, CopyBuffer panics.
//
// If either src implements WriterTo or dst implements ReaderFrom,
// buf will not be used to perform the copy.
func CopyBuffer(dst: Writer, src: Reader, buf: []byte) => (written: i64, err: error) {
if buf != nil && len(buf) == 0 {
panic("empty buffer in CopyBuffer")
}
return copyBuffer(dst, src, buf)
}
// copyBuffer is the actual implementation of Copy and CopyBuffer.
// if buf is nil, one is allocated.
func copyBuffer(dst: Writer, src: Reader, buf: []byte) => (written: i64, err: error) {
// If the reader has a WriteTo method, use it to do the copy.
// Avoids an allocation and a copy.
if wt, ok := src.(WriterTo); ok {
return wt.WriteTo(dst)
}
// Similarly, if the writer has a ReadFrom method, use it to do the copy.
if rt, ok := dst.(ReaderFrom); ok {
return rt.ReadFrom(src)
}
if buf == nil {
size := 32 * 1024
if l, ok := src.(*LimitedReader); ok && int64(size) > l.N {
if l.N < 1 {
size = 1
} else {
size = int(l.N)
}
}
buf = make([]byte, size)
}
for {
nr, er := src.Read(buf)
if nr > 0 {
nw, ew := dst.Write(buf[0:nr])
if nw < 0 || nr < nw {
nw = 0
if ew == nil {
ew = errInvalidWrite
}
}
written += int64(nw)
if ew != nil {
err = ew
break
}
if nr != nw {
err = ErrShortWrite
break
}
}
if er != nil {
if er != EOF {
err = er
}
break
}
}
return written, err
}
// LimitReader returns a Reader that reads from r
// but stops with EOF after n bytes.
// The underlying implementation is a *LimitedReader.
func LimitReader(r: Reader, n: i64) => Reader { return &LimitedReader{r, n} }
// A LimitedReader reads from R but limits the amount of
// data returned to just N bytes. Each call to Read
// updates N to reflect the new amount remaining.
// Read returns EOF when N <= 0 or when the underlying R returns EOF.
type LimitedReader struct {
R :Reader // underlying reader
N :i64 // max bytes remaining
}
func LimitedReader.Read(p: []byte) => (n: int, err: error) {
if this.N <= 0 {
return 0, EOF
}
if int64(len(p)) > this.N {
p = p[0:this.N]
}
n, err = this.R.Read(p)
this.N -= int64(n)
return
}
// NewSectionReader returns a SectionReader that reads from r
// starting at offset off and stops with EOF after n bytes.
func NewSectionReader(r: ReaderAt, off: i64, n: i64) => *SectionReader {
return &SectionReader{r, off, off, off + n}
}
// SectionReader implements Read, Seek, and ReadAt on a section
// of an underlying ReaderAt.
type SectionReader struct {
r :ReaderAt
base :i64
off :i64
limit :i64
}
func SectionReader.Read(p: []byte) => (n: int, err: error) {
if this.off >= this.limit {
return 0, EOF
}
if max := this.limit - this.off; int64(len(p)) > max {
p = p[0:max]
}
n, err = this.r.ReadAt(p, this.off)
this.off += int64(n)
return
}
var errWhence = errors.New("Seek: invalid whence")
var errOffset = errors.New("Seek: invalid offset")
func SectionReader.Seek(offset: i64, whence: int) => (i64, error) {
switch whence {
default:
return 0, errWhence
case SeekStart:
offset += this.base
case SeekCurrent:
offset += this.off
case SeekEnd:
offset += this.limit
}
if offset < this.base {
return 0, errOffset
}
this.off = offset
return offset - this.base, nil
}
func SectionReader.ReadAt(p: []byte, off: i64) => (n: int, err: error) {
if off < 0 || off >= this.limit-this.base {
return 0, EOF
}
off += this.base
if max := this.limit - off; int64(len(p)) > max {
p = p[0:max]
n, err = this.r.ReadAt(p, off)
if err == nil {
err = EOF
}
return n, err
}
return this.r.ReadAt(p, off)
}
// Size returns the size of the section in bytes.
func SectionReader.Size() => i64 { return this.limit - this.base }
// TeeReader returns a Reader that writes to w what it reads from r.
// All reads from r performed through it are matched with
// corresponding writes to w. There is no internal buffering -
// the write must complete before the read completes.
// Any error encountered while writing is reported as a read error.
func TeeReader(r: Reader, w: Writer) => Reader {
return &teeReader{r, w}
}
type teeReader struct {
r :Reader
w :Writer
}
func teeReader.Read(p: []byte) => (n: int, err: error) {
n, err = this.r.Read(p)
if n > 0 {
if n, err := this.w.Write(p[:n]); err != nil {
return n, err
}
}
return
}
// Discard is a Writer on which all Write calls succeed
// without doing anything.
var Discard :Writer = &discard{}
type discard struct{}
// discard implements ReaderFrom as an optimization so Copy to
// io.Discard can avoid doing unnecessary work.
var _ :ReaderFrom = &discard{}
func discard.Write(p: []byte) => (int, error) {
return len(p), nil
}
func discard.WriteString(s: string) => (int, error) {
return len(s), nil
}
func discard.ReadFrom(r: Reader) => (n: i64, err: error) {
panic("TODO")
}
// NopCloser returns a ReadCloser with a no-op Close method wrapping
// the provided Reader r.
func NopCloser(r: Reader) => ReadCloser {
return &nopCloser{r}
}
type nopCloser struct {
Reader
}
func nopCloser.Close() error { return nil }
// ReadAll reads from r until an error or EOF and returns the data it read.
// A successful call returns err == nil, not err == EOF. Because ReadAll is
// defined to read from src until EOF, it does not treat an EOF from Read
// as an error to be reported.
func ReadAll(r: Reader) => ([]byte, error) {
b := make([]byte, 0, 512)
for {
if len(b) == cap(b) {
// Add more capacity (let append pick how much).
b = append(b, 0)[:len(b)]
}
n, err := r.Read(b[len(b):cap(b)])
b = b[:len(b)+n]
if err != nil {
if err == EOF {
err = nil
}
return b, err
}
}
}
// 版权 @2023 凹语言 作者。保留所有权利。
// Abs returns the absolute value of x.
//
// Special cases are:
// Abs(±Inf) = +Inf
// Abs(NaN) = NaN
func Abs(x: f64) => f64 {
if x > 0 {
return x
}
return -x
}
// 版权 @2023 凹语言 作者。保留所有权利。
// Mathematical constants.
const (
E = 2.71828182845904523536028747135266249775724709369995957496696763 // https://oeis.org/A001113
Pi = 3.14159265358979323846264338327950288419716939937510582097494459 // https://oeis.org/A000796
Phi = 1.61803398874989484820458683436563811772030917980576286213544862 // https://oeis.org/A001622
Sqrt2 = 1.41421356237309504880168872420969807856967187537694807317667974 // https://oeis.org/A002193
SqrtE = 1.64872127070012814684865078781416357165377610071014801157507931 // https://oeis.org/A019774
SqrtPi = 1.77245385090551602729816748334114518279754945612238712821380779 // https://oeis.org/A002161
SqrtPhi = 1.27201964951406896425242246173749149171560804184009624861664038 // https://oeis.org/A139339
Ln2 = 0.693147180559945309417232121458176568075500134360255254120680009 // https://oeis.org/A002162
Log2E = 1 / Ln2
Ln10 = 2.30258509299404568401799145468436420760110148862877297603332790 // https://oeis.org/A002392
Log10E = 1 / Ln10
)
// 版权 @2023 凹语言 作者。保留所有权利。
/*
Hypot -- sqrt(p*p + q*q), but overflows only if the result does.
*/
// Hypot returns Sqrt(p*p + q*q), taking care to avoid
// unnecessary overflow and underflow.
//
// Special cases are:
// Hypot(±Inf, q) = +Inf
// Hypot(p, ±Inf) = +Inf
// Hypot(NaN, q) = NaN
// Hypot(p, NaN) = NaN
func Hypot(p, q: f64) => f64 {
return hypot(p, q)
}
func hypot(p, q: f64) => f64 {
// special cases
//switch {
//case IsInf(p, 0) || IsInf(q, 0):
// return Inf(1)
//case IsNaN(p) || IsNaN(q):
// return NaN()
//}
p, q = Abs(p), Abs(q)
if p < q {
p, q = q, p
}
if p == 0 {
return 0
}
q = q / p
return p * Sqrt(1+q*q)
}
// 版权 @2023 凹语言 作者。保留所有权利。
// Sin returns the sine of the radian argument x.
//
// Special cases are:
// Sin(±0) = ±0
// Sin(±Inf) = NaN
// Sin(NaN) = NaN
func Sin(x: f64) => f64 {
return sin(x)
}
// Cos returns the cosine of the radian argument x.
//
// Special cases are:
// Cos(±Inf) = NaN
// Cos(NaN) = NaN
func Cos(x: f64) => f64 {
return cos(x)
}
func sin(x: f64) => f64 {
const (
PI4A = 7.85398125648498535156e-1 // 0x3fe921fb40000000, Pi/4 split into three parts
PI4B = 3.77489470793079817668e-8 // 0x3e64442d00000000,
PI4C = 2.69515142907905952645e-15 // 0x3ce8469898cc5170,
)
//// special cases
//switch {
//case x == 0 || IsNaN(x):
// return x // return ±0 || NaN()
//case IsInf(x, 0):
// return NaN()
//}
// make argument positive but save the sign
sign := false
if x < 0 {
x = -x
sign = true
}
var j: u64
var y, z: f64
//if x >= reduceThreshold {
// j, z = trigReduce(x)
//} else
{
j = u64(x * (4 / Pi)) // integer part of x/(Pi/4), as integer for tests on the phase angle
y = f64(j) // integer part of x/(Pi/4), as float
// map zeros to origin
if j&1 == 1 {
j++
y++
}
j &= 7 // octant modulo 2Pi radians (360 degrees)
z = ((x - y*PI4A) - y*PI4B) - y*PI4C // Extended precision modular arithmetic
}
// reflect in x axis
if j > 3 {
sign = !sign
j -= 4
}
zz := z * z
if j == 1 || j == 2 {
y = 1.0 - 0.5*zz + zz*zz*((((((_cos[0]*zz)+_cos[1])*zz+_cos[2])*zz+_cos[3])*zz+_cos[4])*zz+_cos[5])
} else {
y = z + z*zz*((((((_sin[0]*zz)+_sin[1])*zz+_sin[2])*zz+_sin[3])*zz+_sin[4])*zz+_sin[5])
}
if sign {
y = -y
}
return y
}
// sin coefficients
var _sin = [...]f64{
1.58962301576546568060e-10, // 0x3de5d8fd1fd19ccd
-2.50507477628578072866e-8, // 0xbe5ae5e5a9291f5d
2.75573136213857245213e-6, // 0x3ec71de3567d48a1
-1.98412698295895385996e-4, // 0xbf2a01a019bfdf03
8.33333333332211858878e-3, // 0x3f8111111110f7d0
-1.66666666666666307295e-1, // 0xbfc5555555555548
}
// cos coefficients
var _cos = [...]f64{
-1.13585365213876817300e-11, // 0xbda8fa49a0861a9b
2.08757008419747316778e-9, // 0x3e21ee9d7b4e3f05
-2.75573141792967388112e-7, // 0xbe927e4f7eac4bc6
2.48015872888517045348e-5, // 0x3efa01a019c844f5
-1.38888888888730564116e-3, // 0xbf56c16c16c14f91
4.16666666666665929218e-2, // 0x3fa555555555554b
}
func cos(x: f64) => f64 {
const (
PI4A = 7.85398125648498535156e-1 // 0x3fe921fb40000000, Pi/4 split into three parts
PI4B = 3.77489470793079817668e-8 // 0x3e64442d00000000,
PI4C = 2.69515142907905952645e-15 // 0x3ce8469898cc5170,
)
// special cases
//switch {
//case IsNaN(x) || IsInf(x, 0):
// return NaN()
//}
// make argument positive
sign := false
x = Abs(x)
var j: u64
var y, z: f64
//if x >= reduceThreshold {
// j, z = trigReduce(x)
//} else
{
j = u64(x * (4 / Pi)) // integer part of x/(Pi/4), as integer for tests on the phase angle
y = f64(j) // integer part of x/(Pi/4), as float
// map zeros to origin
if j&1 == 1 {
j++
y++
}
j &= 7 // octant modulo 2Pi radians (360 degrees)
z = ((x - y*PI4A) - y*PI4B) - y*PI4C // Extended precision modular arithmetic
}
if j > 3 {
j -= 4
sign = !sign
}
if j > 1 {
sign = !sign
}
zz := z * z
if j == 1 || j == 2 {
y = z + z*zz*((((((_sin[0]*zz)+_sin[1])*zz+_sin[2])*zz+_sin[3])*zz+_sin[4])*zz+_sin[5])
} else {
y = 1.0 - 0.5*zz + zz*zz*((((((_cos[0]*zz)+_cos[1])*zz+_cos[2])*zz+_cos[3])*zz+_cos[4])*zz+_cos[5])
}
if sign {
y = -y
}
return y
}
// 版权 @2023 凹语言 作者。保留所有权利。
#wa:linkname $$waSqrtF64
func waSqrtF64(x: f64) => f64
// Sqrt returns the square root of x.
//
// Special cases are:
// Sqrt(+Inf) = +Inf
// Sqrt(±0) = ±0
// Sqrt(x < 0) = NaN
// Sqrt(NaN) = NaN
func Sqrt(x: f64) => f64 {
return waSqrtF64(x)
}
;; Copyright 2023 The Wa Authors. All rights reserved.
(func $$waSqrtF64 (param $x f64) (result f64)
local.get $x
f64.sqrt
)
// 版权 @2023 凹语言 作者。保留所有权利。
var Args: []string
#wa:linkname runtime.os_get_args
func os_get_args() => []string
#wa:linkname runtime.os_get_environs
func os_get_environs() => []string
#wa:linkname $runtime.procExit
func Exit(code: i32)
func init {
Args = os_get_args()
}
func Environ() => []string {
return os_get_environs()
}
// 版权 @2023 凹语言 作者。保留所有权利。
// Rob Pike 最小正则实现
// https://www.cs.princeton.edu/courses/archive/spr09/cos333/beautiful.html
func Match(regexp, text: string) => bool {
return match(regexp, text)
}
// match reports whether regexp matches anywhere in text.
func match(regexp, text: string) => bool {
if regexp != "" && regexp[0] == '^' {
return matchHere(regexp[1:], text)
}
for {
if matchHere(regexp, text) {
return true
}
if text == "" {
return false
}
text = text[1:]
}
}
// matchHere reports whether regexp matches at beginning of text.
func matchHere(regexp, text: string) => bool {
switch {
case regexp == "":
return true
case regexp == "$":
return text == ""
case len(regexp) >= 2 && regexp[1] == '*':
return matchStar(regexp[0], regexp[2:], text)
case text != "" && (regexp[0] == '.' || regexp[0] == text[0]):
return matchHere(regexp[1:], text[1:])
}
return false
}
// matchStar reports whether c*regexp matches at beginning of text.
func matchStar(c: byte, regexp, text: string) => bool {
for {
if matchHere(regexp, text) {
return true
}
if text == "" || (text[0] != c && c != '.') {
return false
}
text = text[1:]
}
}
// 版权 @2023 凹语言 作者。保留所有权利。
func TestMatch {
for _, t := range tests {
assert(Match(t.regexp, t.text) == t.ok, t.name + ": Match(" + t.regexp + ", " + t.text + ") failed")
}
}
var tests = []struct {
name :string
regexp :string
text :string
ok :bool
} {
{"wa", "^wa.*$", "wa-lang", true},
{"EmptyBoth", "", "", true},
{"EmptyRegex", "", "wa", true},
{"EmptyText", "wa", "", false},
{"LiteralExact", "wa", "wa", true},
{"LiteralSearch", "wa", "the wa language", true},
{"LiteralNo", "wa", "fb", false},
{"StartOnlyEmpty", "^", "", true},
{"StartOnlySome", "^", "foo", true},
{"StartExact", "^foo", "foo", true},
{"StartInexact", "^foo", "food", true},
{"StartIncomplete", "^foo", "fo", false},
{"StartNo1", "^foo", "xfoo", false},
{"StartNo2", "^foo", "A food truck", false},
{"StartEndEmpty", "^$", "", true},
{"StartEndSome", "^$", "x", false},
{"StartDotEndZero", "^.$", "", false},
{"StartDotEndOne", "^.$", "x", true},
{"StartDotEndTwo", "^.$", "xy", false},
{"EndOnlyEmpty", "$", "", true},
{"EndOnlySome", "$", "foo", true},
{"EndExact", "foo$", "foo", true},
{"EndInexact", "foo$", "xfoo", true},
{"EndIncomplete", "foo$", "oo", false},
{"EndNo1", "foo$", "food", false},
{"EndNo2", "foo$", "A food truck", false},
{"EndAB", "ab$", "abcab", true},
{"CStarOnlyZero", "a*", "", true},
{"CStarOnlyOne", "a*", "a", true},
{"CStarOnlyMany", "a*", "aaaa", true},
{"CStarZero", "fo*d", "fd", true},
{"CStarOne", "fo*d", "fod", true},
{"CStarTwo", "fo*d", "food", true},
{"CStarMany", "fo*d", "fooooood", true},
{"CStarSearch", "fo*d", "A food truck", true},
{"CStarNoEmpty", "fo*d", "", false},
{"CStarNo1", "fo*d", "f", false},
{"CStarNo2", "fo*d", "fx", false},
{"CStarNo3", "fo*d", "fox", false},
{"DotStarZero", "foo.*bar", "foobar", true},
{"DotStarOne", "foo.*bar", "foodbar", true},
{"DotStarMulti", "foo.*bar", "food and bar", true},
{"DotStarSearch", "foo.*bar", "The food bar.", true},
{"DotStarNoEmpty", "foo.*bar", "", false},
{"DotStarNo1", "foo.*bar", "foo", false},
{"DotStarNo2", "foo.*bar", "bar", false},
{"DotStarNo3", "foo.*bar", "fooar", false},
{"DotStarNo4", "foo.*bar", "fobar", false},
{"DotStarSuffixZero", "foo.*", "foo", true},
{"DotStarSuffixSearch", "foo.*", "A food truck", true},
{"DotStarSuffixAnchored", "^foo.*$", "foodie", true},
{"DotStarSuffixAnchoredNo", "^foo.*$", "A food truck", false},
{"DotStarPrefixZero", ".*foo", "foo", true},
{"DotStarPrefixSearch", ".*foo", "A food truck", true},
{"DotStarPrefixAnchored", "^.*foo$", "A foo", true},
{"DotStarPrefixAnchoredNo", "^.*foo$", "A food truck", false},
{"DotStarOnlyZero", ".*", "foo", true},
{"DotStarOnlySearch", ".*", "A food truck", true},
{"DotStarOnlyAnchored", "^.*$", "A foo", true},
{"DotDotExact", "abc..", "abcde", true},
{"DotDotSmall", "abc..", "abcd", false},
{"DotDotLarge", "abc..", "abcdefghijklm", true},
{"DotDotSearch", "abc..", "_abcde_", true},
{"DotDotNo", "abc..", "vwxyz", false},
{"DotSameLengthA", "f.o", "fao", true},
{"DotSameLengthZ", "f.o", "fzo", true},
{"DotSameLengthDot", "f.o", "f.o", true},
{"DotSearch", "f.o", "A fxod truck", true},
{"DotIncomplete", "f.o", "fo", false},
{"DotNo", "f.o", "fxy", false},
{"DotStartYes", ".dog", "The dog", true},
{"DotStartMin", ".dog", "_dog", true},
{"DotStartNo", ".dog", "doggy", false},
{"DotOnlyEmpty", ".", "", false},
{"DotOnlyOne", ".", "a", true},
{"DotOnlyMany", ".", "abcdef", true},
{"DotOnlyAnchored", "^.$", "a", true},
{"DotOnlyAnchoredNo", "^.$", "ab", false},
{"DotCExact", ".a", "xa", true},
{"DotCMore", ".a", "_ya_", true},
{"DotCNo", ".a", "xb", false},
{"CDotExact", "a.", "ax", true},
{"CDotMore", "a.", "_ay_", true},
{"CDotNo", "a.", "bx", false},
}
// 版权 @2023 凹语言 作者。保留所有权利。
// 本文件定义凹语言本身依赖的最小函数列表, 内部函数
// runtime 只能依赖 syscall 包, 不得依赖其它包
// 该文件函数都是其它函数包装, 不含复杂实现逻辑
// TODO: 约定命名规则
// malloc/free
// puts/putchar
// args
// envs
// 版权 @2023 凹语言 作者。保留所有权利。
var assciiTable = [...]string {
"\x00", "\x01", "\x02", "\x03", "\x04", "\x05", "\x06", "\a", "\b", "\t", "\n", "\v", "\f", "\r", "\x0e", "\x0f", "\x10", "\x11", "\x12", "\x13", "\x14", "\x15", "\x16", "\x17", "\x18", "\x19", "\x1a", "\x1b", "\x1c", "\x1d", "\x1e", "\x1f", " ", "!", "\"", "#", "$", "%", "&", "'", "(", ")", "*", "+", ",", "-", ".", "/", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ":", ";", "<", "=", ">", "?", "@", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "[", "\\", "]", "^", "_", "`", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "{", "|", "}", "~", "\u007f",
"\x80", "\x81", "\x82", "\x83", "\x84", "\x85", "\x86", "\x87", "\x88", "\x89", "\x8a", "\x8b", "\x8c", "\x8d", "\x8e", "\x8f", "\x90", "\x91", "\x92", "\x93", "\x94", "\x95", "\x96", "\x97", "\x98", "\x99", "\x9a", "\x9b", "\x9c", "\x9d", "\x9e", "\x9f", "\xa0", "\xa1", "\xa2", "\xa3", "\xa4", "\xa5", "\xa6", "\xa7", "\xa8", "\xa9", "\xaa", "\xab", "\xac", "\xad", "\xae", "\xaf", "\xb0", "\xb1", "\xb2", "\xb3", "\xb4", "\xb5", "\xb6", "\xb7", "\xb8", "\xb9", "\xba", "\xbb", "\xbc", "\xbd", "\xbe", "\xbf", "\xc0", "\xc1", "\xc2", "\xc3", "\xc4", "\xc5", "\xc6", "\xc7", "\xc8", "\xc9", "\xca", "\xcb", "\xcc", "\xcd", "\xce", "\xcf", "\xd0", "\xd1", "\xd2", "\xd3", "\xd4", "\xd5", "\xd6", "\xd7", "\xd8", "\xd9", "\xda", "\xdb", "\xdc", "\xdd", "\xde", "\xdf", "\xe0", "\xe1", "\xe2", "\xe3", "\xe4", "\xe5", "\xe6", "\xe7", "\xe8", "\xe9", "\xea", "\xeb", "\xec", "\xed", "\xee", "\xef", "\xf0", "\xf1", "\xf2", "\xf3", "\xf4", "\xf5", "\xf6", "\xf7", "\xf8", "\xf9", "\xfa", "\xfb", "\xfc", "\xfd", "\xfe", "\xff",
}
func bytes2str(b: []byte) => string {
var s: string
for _, x := range b {
s += assciiTable[x]
}
return s
}
func getCStr(b: []byte, start: i32) => string {
var end: i32 = i32(len(b))
for i := start; i < end; i++ {
if b[i] == 0 {
end = i32(i);
break
}
}
return bytes2str(b[start:end])
}
func os_get_args() => []string {
var argc: i32
var argv_buf_size: i32
argsSizesGet(refToPtr_i32(&argc), refToPtr_i32(&argv_buf_size))
if argc == 0 {
return nil
}
var argvBytes = make([]byte, argc*4)
var argvU32 = make([]u32, argc)
var argv_buf = make([]byte, argv_buf_size)
var argv_buf_ptr: i32 = refToPtr_byteSlice(argv_buf)
argsGet(refToPtr_byteSlice(argvBytes), argv_buf_ptr)
for i := 0; i < len(argvBytes); i += 4 {
a0 := u32(argvBytes[i+0]);
a1 := u32(argvBytes[i+1]);
a2 := u32(argvBytes[i+2]);
a3 := u32(argvBytes[i+3]);
argvU32[i/4] = a0 + a1*256 + a2*256*256 + a3*256*256*256
}
var args = make([]string, argc)
for i := 0; i < int(argc); i++ {
var off = i32(argvU32[i]) - argv_buf_ptr
args[i] = getCStr(argv_buf, off)
}
return args
}
\ No newline at end of file
// 版权 @2023 凹语言 作者。保留所有权利。
func os_get_environs() => []string {
var environc: i32
var environv_buf_size: i32
environSizesGet(refToPtr_i32(&environc), refToPtr_i32(&environv_buf_size))
if environc == 0 {
return nil
}
var environvBytes = make([]byte, environc*4)
var environvU32 = make([]u32, environc)
var environv_buf = make([]byte, environv_buf_size)
var environv_buf_ptr: i32 = refToPtr_byteSlice(environv_buf)
environGet(refToPtr_byteSlice(environvBytes), environv_buf_ptr)
for i := 0; i < len(environvBytes); i += 4 {
a0 := u32(environvBytes[i+0]);
a1 := u32(environvBytes[i+1]);
a2 := u32(environvBytes[i+2]);
a3 := u32(environvBytes[i+3]);
environvU32[i/4] = a0 + a1*256 + a2*256*256 + a3*256*256*256
}
var environs = make([]string, environc)
for i := 0; i < int(environc); i++ {
var off = i32(environvU32[i]) - environv_buf_ptr
environs[i] = getCStr(environv_buf, off)
}
return environs
}
// 版权 @2023 凹语言 作者。保留所有权利。
// ParseBool returns the boolean value represented by the string.
// It accepts 1, t, T, TRUE, true, True, 0, f, F, FALSE, false, False.
// Any other value returns an error.
func ParseBool(str: string) => (bool, error) {
switch str {
case "1", "t", "T", "true", "TRUE", "True":
return true, nil
case "0", "f", "F", "false", "FALSE", "False":
return false, nil
}
return false, syntaxError("ParseBool", str)
}
// FormatBool returns "true" or "false" according to the value of b.
func FormatBool(b: bool) => string {
if b {
return "true"
}
return "false"
}
// AppendBool appends "true" or "false", according to the value of b,
// to dst and returns the extended buffer.
func AppendBool(dst: []byte, b: bool) => []byte {
if b {
return append(dst, "true"...)
}
return append(dst, "false"...)
}
此差异已折叠。
此差异已折叠。
// 版权 @2022 凹语言 作者。保留所有权利。
// https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#functions
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册