tag v0.155.0 Tagger: imagebuilder-bot <imagebuilder-bots+imagebuilder-bot@redhat.com> Changes with 0.155.0 ---------------- * Fedora 43: add shadow-utils when LockRoot is enabled, update cloud-init service name (osbuild/images#1618) * Author: Achilleas Koutsou, Reviewers: Gianluca Zuccarelli, Michael Vogt * Update osbuild dependency commit ID to latest (osbuild/images#1609) * Author: SchutzBot, Reviewers: Achilleas Koutsou, Simon de Vlieger, Tomáš Hozza * Update snapshots to 20250626 (osbuild/images#1623) * Author: SchutzBot, Reviewers: Achilleas Koutsou, Simon de Vlieger * distro/rhel9: xz compress azure-cvm image type [HMS-8587] (osbuild/images#1620) * Author: Achilleas Koutsou, Reviewers: Simon de Vlieger, Tomáš Hozza * distro/rhel: introduce new image type: Azure SAP Apps [HMS-8738] (osbuild/images#1612) * Author: Achilleas Koutsou, Reviewers: Simon de Vlieger, Tomáš Hozza * distro/rhel: move ansible-core to sap_extras_pkgset (osbuild/images#1624) * Author: Achilleas Koutsou, Reviewers: Brian C. Lane, Tomáš Hozza * github/create-tag: allow passing the version when run manually (osbuild/images#1621) * Author: Achilleas Koutsou, Reviewers: Lukáš Zapletal, Tomáš Hozza * rhel9: move image-config into pure YAML (HMS-8593) (osbuild/images#1616) * Author: Michael Vogt, Reviewers: Achilleas Koutsou, Simon de Vlieger * test: split manifest checksums into separate files (osbuild/images#1625) * Author: Achilleas Koutsou, Reviewers: Simon de Vlieger, Tomáš Hozza — Somewhere on the Internet, 2025-06-30 --- tag v0.156.0 Tagger: imagebuilder-bot <imagebuilder-bots+imagebuilder-bot@redhat.com> Changes with 0.156.0 ---------------- * Many: delete repositories for EOL distributions (HMS-7044) (osbuild/images#1607) * Author: Tomáš Hozza, Reviewers: Michael Vogt, Simon de Vlieger * RHSM/facts: add 'image-builder CLI' API type (osbuild/images#1640) * Author: Tomáš Hozza, Reviewers: Brian C. Lane, Simon de Vlieger * Update dependencies 2025-06-29 (osbuild/images#1628) * Author: SchutzBot, Reviewers: Simon de Vlieger, Tomáš Hozza * Update osbuild dependency commit ID to latest (osbuild/images#1627) * Author: SchutzBot, Reviewers: Simon de Vlieger, Tomáš Hozza * [RFC] image: drop `InstallWeakDeps` from image.DiskImage (osbuild/images#1642) * Author: Michael Vogt, Reviewers: Brian C. Lane, Simon de Vlieger, Tomáš Hozza * build(deps): bump the go-deps group across 1 directory with 3 updates (osbuild/images#1632) * Author: dependabot[bot], Reviewers: SchutzBot, Tomáš Hozza * distro/rhel10: xz compress azure-cvm image type (osbuild/images#1638) * Author: Achilleas Koutsou, Reviewers: Brian C. Lane, Simon de Vlieger * distro: cleanup/refactor distro/{defs,generic} (HMS-8744) (osbuild/images#1570) * Author: Michael Vogt, Reviewers: Simon de Vlieger, Tomáš Hozza * distro: remove some hardcoded values from generic/images.go (osbuild/images#1636) * Author: Michael Vogt, Reviewers: Simon de Vlieger, Tomáš Hozza * distro: small tweaks for the YAML based imagetypes (osbuild/images#1622) * Author: Michael Vogt, Reviewers: Brian C. Lane, Simon de Vlieger * fedora/wsl: packages and locale (osbuild/images#1635) * Author: Simon de Vlieger, Reviewers: Michael Vogt, Tomáš Hozza * image/many: make compression more generic (osbuild/images#1634) * Author: Simon de Vlieger, Reviewers: Brian C. Lane, Michael Vogt * manifest: handle content template name with spaces (osbuild/images#1641) * Author: Bryttanie, Reviewers: Brian C. Lane, Michael Vogt, Tomáš Hozza * many: implement gzip (osbuild/images#1633) * Author: Simon de Vlieger, Reviewers: Michael Vogt, Tomáš Hozza * rhel/azure: set GRUB_TERMINAL based on architecture [RHEL-91383] (osbuild/images#1626) * Author: Achilleas Koutsou, Reviewers: Simon de Vlieger, Tomáš Hozza — Somewhere on the Internet, 2025-07-07 ---
417 lines
10 KiB
Go
417 lines
10 KiB
Go
// Package jwriter contains a JSON writer.
|
|
package jwriter
|
|
|
|
import (
|
|
"io"
|
|
"strconv"
|
|
"unicode/utf8"
|
|
|
|
"github.com/mailru/easyjson/buffer"
|
|
)
|
|
|
|
// Flags describe various encoding options. The behavior may be actually implemented in the encoder, but
|
|
// Flags field in Writer is used to set and pass them around.
|
|
type Flags int
|
|
|
|
const (
|
|
NilMapAsEmpty Flags = 1 << iota // Encode nil map as '{}' rather than 'null'.
|
|
NilSliceAsEmpty // Encode nil slice as '[]' rather than 'null'.
|
|
)
|
|
|
|
// Writer is a JSON writer.
|
|
type Writer struct {
|
|
Flags Flags
|
|
|
|
Error error
|
|
Buffer buffer.Buffer
|
|
NoEscapeHTML bool
|
|
}
|
|
|
|
// Size returns the size of the data that was written out.
|
|
func (w *Writer) Size() int {
|
|
return w.Buffer.Size()
|
|
}
|
|
|
|
// DumpTo outputs the data to given io.Writer, resetting the buffer.
|
|
func (w *Writer) DumpTo(out io.Writer) (written int, err error) {
|
|
return w.Buffer.DumpTo(out)
|
|
}
|
|
|
|
// BuildBytes returns writer data as a single byte slice. You can optionally provide one byte slice
|
|
// as argument that it will try to reuse.
|
|
func (w *Writer) BuildBytes(reuse ...[]byte) ([]byte, error) {
|
|
if w.Error != nil {
|
|
return nil, w.Error
|
|
}
|
|
|
|
return w.Buffer.BuildBytes(reuse...), nil
|
|
}
|
|
|
|
// ReadCloser returns an io.ReadCloser that can be used to read the data.
|
|
// ReadCloser also resets the buffer.
|
|
func (w *Writer) ReadCloser() (io.ReadCloser, error) {
|
|
if w.Error != nil {
|
|
return nil, w.Error
|
|
}
|
|
|
|
return w.Buffer.ReadCloser(), nil
|
|
}
|
|
|
|
// RawByte appends raw binary data to the buffer.
|
|
func (w *Writer) RawByte(c byte) {
|
|
w.Buffer.AppendByte(c)
|
|
}
|
|
|
|
// RawByte appends raw binary data to the buffer.
|
|
func (w *Writer) RawString(s string) {
|
|
w.Buffer.AppendString(s)
|
|
}
|
|
|
|
// RawBytesString appends string from bytes to the buffer.
|
|
func (w *Writer) RawBytesString(data []byte, err error) {
|
|
switch {
|
|
case w.Error != nil:
|
|
return
|
|
case err != nil:
|
|
w.Error = err
|
|
default:
|
|
w.String(string(data))
|
|
}
|
|
}
|
|
|
|
// Raw appends raw binary data to the buffer or sets the error if it is given. Useful for
|
|
// calling with results of MarshalJSON-like functions.
|
|
func (w *Writer) Raw(data []byte, err error) {
|
|
switch {
|
|
case w.Error != nil:
|
|
return
|
|
case err != nil:
|
|
w.Error = err
|
|
case len(data) > 0:
|
|
w.Buffer.AppendBytes(data)
|
|
default:
|
|
w.RawString("null")
|
|
}
|
|
}
|
|
|
|
// RawText encloses raw binary data in quotes and appends in to the buffer.
|
|
// Useful for calling with results of MarshalText-like functions.
|
|
func (w *Writer) RawText(data []byte, err error) {
|
|
switch {
|
|
case w.Error != nil:
|
|
return
|
|
case err != nil:
|
|
w.Error = err
|
|
case len(data) > 0:
|
|
w.String(string(data))
|
|
default:
|
|
w.RawString("null")
|
|
}
|
|
}
|
|
|
|
// Base64Bytes appends data to the buffer after base64 encoding it
|
|
func (w *Writer) Base64Bytes(data []byte) {
|
|
if data == nil {
|
|
w.Buffer.AppendString("null")
|
|
return
|
|
}
|
|
w.Buffer.AppendByte('"')
|
|
w.base64(data)
|
|
w.Buffer.AppendByte('"')
|
|
}
|
|
|
|
func (w *Writer) Uint8(n uint8) {
|
|
w.Buffer.EnsureSpace(3)
|
|
w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10)
|
|
}
|
|
|
|
func (w *Writer) Uint16(n uint16) {
|
|
w.Buffer.EnsureSpace(5)
|
|
w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10)
|
|
}
|
|
|
|
func (w *Writer) Uint32(n uint32) {
|
|
w.Buffer.EnsureSpace(10)
|
|
w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10)
|
|
}
|
|
|
|
func (w *Writer) Uint(n uint) {
|
|
w.Buffer.EnsureSpace(20)
|
|
w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10)
|
|
}
|
|
|
|
func (w *Writer) Uint64(n uint64) {
|
|
w.Buffer.EnsureSpace(20)
|
|
w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, n, 10)
|
|
}
|
|
|
|
func (w *Writer) Int8(n int8) {
|
|
w.Buffer.EnsureSpace(4)
|
|
w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, int64(n), 10)
|
|
}
|
|
|
|
func (w *Writer) Int16(n int16) {
|
|
w.Buffer.EnsureSpace(6)
|
|
w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, int64(n), 10)
|
|
}
|
|
|
|
func (w *Writer) Int32(n int32) {
|
|
w.Buffer.EnsureSpace(11)
|
|
w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, int64(n), 10)
|
|
}
|
|
|
|
func (w *Writer) Int(n int) {
|
|
w.Buffer.EnsureSpace(21)
|
|
w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, int64(n), 10)
|
|
}
|
|
|
|
func (w *Writer) Int64(n int64) {
|
|
w.Buffer.EnsureSpace(21)
|
|
w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, n, 10)
|
|
}
|
|
|
|
func (w *Writer) Uint8Str(n uint8) {
|
|
w.Buffer.EnsureSpace(3)
|
|
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
|
w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10)
|
|
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
|
}
|
|
|
|
func (w *Writer) Uint16Str(n uint16) {
|
|
w.Buffer.EnsureSpace(5)
|
|
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
|
w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10)
|
|
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
|
}
|
|
|
|
func (w *Writer) Uint32Str(n uint32) {
|
|
w.Buffer.EnsureSpace(10)
|
|
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
|
w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10)
|
|
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
|
}
|
|
|
|
func (w *Writer) UintStr(n uint) {
|
|
w.Buffer.EnsureSpace(20)
|
|
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
|
w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10)
|
|
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
|
}
|
|
|
|
func (w *Writer) Uint64Str(n uint64) {
|
|
w.Buffer.EnsureSpace(20)
|
|
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
|
w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, n, 10)
|
|
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
|
}
|
|
|
|
func (w *Writer) UintptrStr(n uintptr) {
|
|
w.Buffer.EnsureSpace(20)
|
|
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
|
w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10)
|
|
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
|
}
|
|
|
|
func (w *Writer) Int8Str(n int8) {
|
|
w.Buffer.EnsureSpace(4)
|
|
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
|
w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, int64(n), 10)
|
|
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
|
}
|
|
|
|
func (w *Writer) Int16Str(n int16) {
|
|
w.Buffer.EnsureSpace(6)
|
|
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
|
w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, int64(n), 10)
|
|
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
|
}
|
|
|
|
func (w *Writer) Int32Str(n int32) {
|
|
w.Buffer.EnsureSpace(11)
|
|
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
|
w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, int64(n), 10)
|
|
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
|
}
|
|
|
|
func (w *Writer) IntStr(n int) {
|
|
w.Buffer.EnsureSpace(21)
|
|
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
|
w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, int64(n), 10)
|
|
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
|
}
|
|
|
|
func (w *Writer) Int64Str(n int64) {
|
|
w.Buffer.EnsureSpace(21)
|
|
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
|
w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, n, 10)
|
|
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
|
}
|
|
|
|
func (w *Writer) Float32(n float32) {
|
|
w.Buffer.EnsureSpace(20)
|
|
w.Buffer.Buf = strconv.AppendFloat(w.Buffer.Buf, float64(n), 'g', -1, 32)
|
|
}
|
|
|
|
func (w *Writer) Float32Str(n float32) {
|
|
w.Buffer.EnsureSpace(20)
|
|
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
|
w.Buffer.Buf = strconv.AppendFloat(w.Buffer.Buf, float64(n), 'g', -1, 32)
|
|
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
|
}
|
|
|
|
func (w *Writer) Float64(n float64) {
|
|
w.Buffer.EnsureSpace(20)
|
|
w.Buffer.Buf = strconv.AppendFloat(w.Buffer.Buf, n, 'g', -1, 64)
|
|
}
|
|
|
|
func (w *Writer) Float64Str(n float64) {
|
|
w.Buffer.EnsureSpace(20)
|
|
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
|
w.Buffer.Buf = strconv.AppendFloat(w.Buffer.Buf, float64(n), 'g', -1, 64)
|
|
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
|
}
|
|
|
|
func (w *Writer) Bool(v bool) {
|
|
w.Buffer.EnsureSpace(5)
|
|
if v {
|
|
w.Buffer.Buf = append(w.Buffer.Buf, "true"...)
|
|
} else {
|
|
w.Buffer.Buf = append(w.Buffer.Buf, "false"...)
|
|
}
|
|
}
|
|
|
|
const chars = "0123456789abcdef"
|
|
|
|
func getTable(falseValues ...int) [128]bool {
|
|
table := [128]bool{}
|
|
|
|
for i := 0; i < 128; i++ {
|
|
table[i] = true
|
|
}
|
|
|
|
for _, v := range falseValues {
|
|
table[v] = false
|
|
}
|
|
|
|
return table
|
|
}
|
|
|
|
var (
|
|
htmlEscapeTable = getTable(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, '"', '&', '<', '>', '\\')
|
|
htmlNoEscapeTable = getTable(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, '"', '\\')
|
|
)
|
|
|
|
func (w *Writer) String(s string) {
|
|
w.Buffer.AppendByte('"')
|
|
|
|
// Portions of the string that contain no escapes are appended as
|
|
// byte slices.
|
|
|
|
p := 0 // last non-escape symbol
|
|
|
|
escapeTable := &htmlEscapeTable
|
|
if w.NoEscapeHTML {
|
|
escapeTable = &htmlNoEscapeTable
|
|
}
|
|
|
|
for i := 0; i < len(s); {
|
|
c := s[i]
|
|
|
|
if c < utf8.RuneSelf {
|
|
if escapeTable[c] {
|
|
// single-width character, no escaping is required
|
|
i++
|
|
continue
|
|
}
|
|
|
|
w.Buffer.AppendString(s[p:i])
|
|
switch c {
|
|
case '\t':
|
|
w.Buffer.AppendString(`\t`)
|
|
case '\r':
|
|
w.Buffer.AppendString(`\r`)
|
|
case '\n':
|
|
w.Buffer.AppendString(`\n`)
|
|
case '\\':
|
|
w.Buffer.AppendString(`\\`)
|
|
case '"':
|
|
w.Buffer.AppendString(`\"`)
|
|
default:
|
|
w.Buffer.AppendString(`\u00`)
|
|
w.Buffer.AppendByte(chars[c>>4])
|
|
w.Buffer.AppendByte(chars[c&0xf])
|
|
}
|
|
|
|
i++
|
|
p = i
|
|
continue
|
|
}
|
|
|
|
// broken utf
|
|
runeValue, runeWidth := utf8.DecodeRuneInString(s[i:])
|
|
if runeValue == utf8.RuneError && runeWidth == 1 {
|
|
w.Buffer.AppendString(s[p:i])
|
|
w.Buffer.AppendString(`\ufffd`)
|
|
i++
|
|
p = i
|
|
continue
|
|
}
|
|
|
|
// jsonp stuff - tab separator and line separator
|
|
if runeValue == '\u2028' || runeValue == '\u2029' {
|
|
w.Buffer.AppendString(s[p:i])
|
|
w.Buffer.AppendString(`\u202`)
|
|
w.Buffer.AppendByte(chars[runeValue&0xf])
|
|
i += runeWidth
|
|
p = i
|
|
continue
|
|
}
|
|
i += runeWidth
|
|
}
|
|
w.Buffer.AppendString(s[p:])
|
|
w.Buffer.AppendByte('"')
|
|
}
|
|
|
|
const encode = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
|
|
const padChar = '='
|
|
|
|
func (w *Writer) base64(in []byte) {
|
|
|
|
if len(in) == 0 {
|
|
return
|
|
}
|
|
|
|
w.Buffer.EnsureSpace(((len(in)-1)/3 + 1) * 4)
|
|
|
|
si := 0
|
|
n := (len(in) / 3) * 3
|
|
|
|
for si < n {
|
|
// Convert 3x 8bit source bytes into 4 bytes
|
|
val := uint(in[si+0])<<16 | uint(in[si+1])<<8 | uint(in[si+2])
|
|
|
|
w.Buffer.Buf = append(w.Buffer.Buf, encode[val>>18&0x3F], encode[val>>12&0x3F], encode[val>>6&0x3F], encode[val&0x3F])
|
|
|
|
si += 3
|
|
}
|
|
|
|
remain := len(in) - si
|
|
if remain == 0 {
|
|
return
|
|
}
|
|
|
|
// Add the remaining small block
|
|
val := uint(in[si+0]) << 16
|
|
if remain == 2 {
|
|
val |= uint(in[si+1]) << 8
|
|
}
|
|
|
|
w.Buffer.Buf = append(w.Buffer.Buf, encode[val>>18&0x3F], encode[val>>12&0x3F])
|
|
|
|
switch remain {
|
|
case 2:
|
|
w.Buffer.Buf = append(w.Buffer.Buf, encode[val>>6&0x3F], byte(padChar))
|
|
case 1:
|
|
w.Buffer.Buf = append(w.Buffer.Buf, byte(padChar), byte(padChar))
|
|
}
|
|
}
|