Add user defined system message

This commit is contained in:
dwrz
2026-05-28 00:53:08 +00:00
parent a06833bb8b
commit 9ea4005e96
26 changed files with 652 additions and 222 deletions

View File

@@ -12,7 +12,7 @@ llm:
url: "http://localhost:8081/v1"
key: ${ODIDERE_LLM_KEY}
model: "default"
system_prompt: "You are a helpful voice assistant. Be concise."
system_message: "You are a helpful voice assistant. Be concise."
timeout: "5m"
tts:

View File

@@ -22,8 +22,8 @@ type Config struct {
Key string `yaml:"key"`
// Model is the model identifier.
Model string `yaml:"model"`
// SystemPrompt is prepended to all conversations.
SystemPrompt string `yaml:"system_prompt"`
// SystemMessage is prepended to all conversations.
SystemMessage string `yaml:"system_message"`
// Timeout is the maximum duration for a query (e.g., "5m").
// Defaults to 5 minutes if empty.
Timeout string `yaml:"timeout"`
@@ -49,13 +49,13 @@ func (cfg Config) Validate() error {
// Client wraps an OpenAI-compatible client with tool execution support.
type Client struct {
client *openai.Client
log *slog.Logger
model string
registry *tool.Registry
systemPrompt string
timeout time.Duration
tools []openai.Tool
client *openai.Client
log *slog.Logger
model string
registry *tool.Registry
systemMessage string
timeout time.Duration
tools []openai.Tool
}
// NewClient creates a new LLM client with the provided configuration.
@@ -70,10 +70,10 @@ func NewClient(
}
llm := &Client{
log: log,
model: cfg.Model,
systemPrompt: cfg.SystemPrompt,
registry: registry,
log: log,
model: cfg.Model,
systemMessage: cfg.SystemMessage,
registry: registry,
}
if cfg.Timeout == "" {
@@ -122,12 +122,14 @@ func (c *Client) DefaultModel() string {
// Query sends messages to the LLM using the specified model.
// If model is empty, uses the default configured model.
// If systemMessage is non-empty, it overrides the configured system message.
// Returns all messages generated during the query, including tool calls
// and tool results. The final message is the last element in the slice.
func (c *Client) Query(
ctx context.Context,
messages []openai.ChatCompletionMessage,
model string,
systemMessage string,
) ([]openai.ChatCompletionMessage, error) {
ctx, cancel := context.WithTimeout(ctx, c.timeout)
defer cancel()
@@ -137,13 +139,19 @@ func (c *Client) Query(
model = c.model
}
// Prepend system prompt, if configured and not already present.
if c.systemPrompt != "" && (len(messages) == 0 ||
// Use per-request system message if provided, otherwise fall back to config.
effectiveMessage := c.systemMessage
if systemMessage != "" {
effectiveMessage = systemMessage
}
// Prepend system message, if configured and not already present.
if effectiveMessage != "" && (len(messages) == 0 ||
messages[0].Role != openai.ChatMessageRoleSystem) {
messages = append(
[]openai.ChatCompletionMessage{{
Role: openai.ChatMessageRoleSystem,
Content: c.systemPrompt,
Content: effectiveMessage,
}},
messages...,
)
@@ -239,11 +247,13 @@ type StreamEvent struct {
// streams results. Each complete message (assistant reply, tool call,
// tool result) is sent to the events channel as it becomes available.
// The channel is closed before returning.
// If systemMessage is non-empty, it overrides the configured system message.
// Returns all messages generated during the query.
func (c *Client) QueryStream(
ctx context.Context,
messages []openai.ChatCompletionMessage,
model string,
systemMessage string,
events chan<- StreamEvent,
) error {
defer close(events)
@@ -256,13 +266,19 @@ func (c *Client) QueryStream(
model = c.model
}
// Prepend system prompt, if configured and not already present.
if c.systemPrompt != "" && (len(messages) == 0 ||
// Use per-request system message if provided, otherwise fall back to config.
effectiveMessage := c.systemMessage
if systemMessage != "" {
effectiveMessage = systemMessage
}
// Prepend system message, if configured and not already present.
if effectiveMessage != "" && (len(messages) == 0 ||
messages[0].Role != openai.ChatMessageRoleSystem) {
messages = append(
[]openai.ChatCompletionMessage{{
Role: openai.ChatMessageRoleSystem,
Content: c.systemPrompt,
Content: effectiveMessage,
}},
messages...,
)

View File

@@ -67,11 +67,11 @@ func TestConfigValidate(t *testing.T) {
{
name: "valid full config",
cfg: Config{
Key: "sk-test-key",
Model: "test-model",
SystemPrompt: "You are a helpful assistant.",
Timeout: "30m",
URL: "http://localhost:8080",
Key: "sk-test-key",
Model: "test-model",
SystemMessage: "You are a helpful assistant.",
Timeout: "30m",
URL: "http://localhost:8080",
},
wantErr: false,
},
@@ -121,11 +121,11 @@ func TestNewClient(t *testing.T) {
{
name: "valid config with all fields",
cfg: Config{
Key: "test-key",
Model: "test-model",
SystemPrompt: "Test prompt",
Timeout: "5m",
URL: "http://localhost:8080",
Key: "test-key",
Model: "test-model",
SystemMessage: "Test message",
Timeout: "5m",
URL: "http://localhost:8080",
},
wantErr: false,
},

View File

@@ -311,6 +311,8 @@ type Request struct {
Messages []openai.ChatCompletionMessage `json:"messages"`
// Model is the LLM model ID. If empty, the default model is used.
Model string `json:"model,omitempty"`
// SystemMessage overrides the configured system message for this request.
SystemMessage string `json:"system_message,omitempty"`
// Voice is the voice ID for TTS.
Voice string `json:"voice,omitempty"`
}
@@ -455,7 +457,7 @@ func (svc *Service) voice(w http.ResponseWriter, r *http.Request) {
if model == "" {
model = svc.llm.DefaultModel()
}
msgs, err := svc.llm.Query(ctx, messages, model)
msgs, err := svc.llm.Query(ctx, messages, model, req.SystemMessage)
if err != nil {
log.ErrorContext(
ctx,
@@ -731,7 +733,7 @@ func (svc *Service) voiceStream(w http.ResponseWriter, r *http.Request) {
llmErr error
)
go func() {
llmErr = svc.llm.QueryStream(ctx, messages, model, events)
llmErr = svc.llm.QueryStream(ctx, messages, model, req.SystemMessage, events)
}()
// Consume events and send as SSE.

View File

@@ -90,4 +90,9 @@
<path d="m15 9-6 6"/>
<path d="m9 9 6 6"/>
</symbol>
<symbol id="settings" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z"/>
<circle cx="12" cy="12" r="3"/>
</symbol>
</svg>

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

View File

@@ -593,6 +593,201 @@ body {
color: var(--color-text-muted);
}
/* ==================== */
/* Settings Modal */
/* ==================== */
.settings-overlay {
display: none;
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.5);
z-index: 1000;
align-items: center;
justify-content: center;
padding: var(--s1);
}
.settings-overlay.open {
display: flex;
}
.settings-panel {
background: var(--color-surface);
border: 1px solid var(--color-border-light);
border-radius: var(--radius);
width: 100%;
max-width: 480px;
max-height: 90vh;
overflow-y: auto;
padding: var(--s1);
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.15);
}
.settings-panel__header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: var(--s1);
}
.settings-panel__title {
font-size: var(--s1);
font-weight: 600;
color: var(--color-text);
margin: 0;
}
/* Close button: remove toolbar border, darken the X. */
#settings-close {
border: none;
color: var(--color-text);
}
@media (hover: hover) {
#settings-close:hover {
border-color: transparent;
color: var(--color-text);
}
}
/* Tabs */
.settings-tabs {
display: flex;
border-bottom: 2px solid var(--color-border-light);
margin-bottom: var(--s1);
}
.settings-tab {
padding: var(--s-2) var(--s-1);
background: transparent;
border: none;
border-bottom: 2px solid transparent;
margin-bottom: -2px;
font-family: inherit;
font-size: var(--s-1);
color: var(--color-text-muted);
cursor: pointer;
transition: all 0.15s ease;
}
@media (hover: hover) {
.settings-tab:hover {
color: var(--color-text);
}
}
.settings-tab:focus-visible {
outline: 2px solid var(--color-primary);
outline-offset: -2px;
}
.settings-tab.active {
color: var(--color-text);
border-bottom-color: var(--color-primary);
font-weight: 500;
}
/* Tab panels */
.settings-tab-panel {
display: none;
}
.settings-tab-panel.active {
display: block;
}
.settings-label {
display: block;
font-size: var(--s-1);
font-weight: 500;
color: var(--color-text);
margin-bottom: var(--s-2);
}
.settings-select {
width: 100%;
height: var(--s2);
padding: 0 var(--s-1);
font-family: inherit;
font-size: var(--s-1);
line-height: var(--s2);
color: var(--color-text);
background: var(--color-surface);
border: 1px solid var(--color-border-light);
border-radius: var(--radius);
cursor: pointer;
margin-bottom: var(--s1);
}
.settings-select:focus-visible {
outline: 2px solid var(--color-primary);
outline-offset: 2px;
}
.settings-textarea {
display: block;
width: 100%;
min-height: calc(var(--s2) * 6);
padding: var(--s-1);
font-family: var(--font-mono);
font-size: var(--s-1);
line-height: 1.5;
color: var(--color-text);
background: var(--color-bg);
border: 1px solid var(--color-border-light);
border-radius: var(--radius);
resize: vertical;
margin-bottom: var(--s-1);
}
.settings-textarea:focus {
outline: 2px solid var(--color-primary);
outline-offset: 1px;
}
.settings-save-row {
display: flex;
justify-content: flex-end;
}
.settings-save-btn {
display: flex;
align-items: center;
justify-content: center;
padding: var(--s-2) var(--s-1);
font-family: inherit;
font-size: var(--s-1);
font-weight: 500;
color: white;
background: var(--color-primary);
border: none;
border-radius: var(--radius);
cursor: pointer;
transition: background-color 0.15s ease;
min-width: var(--s2);
}
@media (hover: hover) {
.settings-save-btn:hover {
background: var(--color-primary-hover);
}
}
.settings-save-btn:focus-visible {
outline: 2px solid var(--color-primary);
outline-offset: 2px;
}
.settings-save-btn--success {
background: var(--color-green);
}
.settings-save-btn .icon {
width: 1rem;
height: 1rem;
}
/* ==================== */
/* Animations */
/* ==================== */
@@ -668,4 +863,16 @@ body {
max-width: 128px;
font-size: var(--s-1);
}
.settings-overlay {
padding: 0;
}
.settings-panel {
max-width: 100%;
max-height: 100dvh;
height: 100dvh;
border-radius: 0;
border: none;
}
}

View File

@@ -3,6 +3,7 @@ const ICONS_URL = '/static/icons.svg';
const MODELS_ENDPOINT = '/v1/models';
const MODEL_KEY = 'odidere_model';
const STORAGE_KEY = 'odidere_history';
const SYSTEM_MESSAGE_KEY = 'odidere_system_message';
const VOICES_ENDPOINT = '/v1/voices';
const VOICE_KEY = 'odidere_voice';
@@ -42,6 +43,15 @@ class Odidere {
this.$voice = document.getElementById('voice');
this.$mute = document.getElementById('mute');
// Settings modal
this.$settings = document.getElementById('settings');
this.$settingsOverlay = document.getElementById('settings-overlay');
this.$settingsClose = document.getElementById('settings-close');
this.$settingsTabs = document.querySelectorAll('.settings-tab');
this.$settingsPanels = document.querySelectorAll('.settings-tab-panel');
this.$systemMessageInput = document.getElementById('system-message-input');
this.$saveSystemMessage = document.getElementById('save-system-message');
// Templates
this.$tplAssistantMessage = document.getElementById(
'tpl-assistant-message',
@@ -151,6 +161,28 @@ class Odidere {
});
// Mute button
this.$mute.addEventListener('click', () => this.#toggleMute());
// Settings modal
this.$settings.addEventListener('click', () => this.openSettings());
this.$settingsClose.addEventListener('click', () => this.closeSettings());
this.$settingsOverlay.addEventListener('click', (e) => {
if (e.target === this.$settingsOverlay) this.closeSettings();
});
this.document.addEventListener('keydown', (e) => {
if (
e.key === 'Escape' &&
this.$settingsOverlay.classList.contains('open')
) {
e.preventDefault();
this.closeSettings();
}
});
this.$settingsTabs.forEach(($tab) => {
$tab.addEventListener('click', () => this.#switchTab($tab.dataset.tab));
});
this.$saveSystemMessage.addEventListener('click', () =>
this.#saveSystemMessage(),
);
}
/**
@@ -557,6 +589,10 @@ class Odidere {
voice: this.$voice.value,
model: this.$model.value,
};
const systemMessage = localStorage.getItem(SYSTEM_MESSAGE_KEY);
if (systemMessage) {
payload.system_message = systemMessage;
}
if (audio) {
payload.audio = await this.#toBase64(audio);
}
@@ -674,7 +710,11 @@ class Odidere {
}
// Collect tool results and render once all have arrived.
if (message.role === 'tool' && pendingTools && pendingTools.assistant) {
if (
message.role === 'tool' &&
pendingTools &&
pendingTools.assistant
) {
pendingTools.results.push(message);
// Add to history (server needs it) but don't render yet.
this.#appendHistory([message]);
@@ -849,6 +889,67 @@ class Odidere {
}
}
/**
* openSettings opens the settings modal and loads current values.
*/
openSettings() {
this.$settingsOverlay.classList.add('open');
this.#loadSystemMessage();
this.#switchTab('model-voice');
// Focus the close button for accessibility.
this.$settingsClose.focus();
}
/**
* closeSettings closes the settings modal and restores focus.
*/
closeSettings() {
this.$settingsOverlay.classList.remove('open');
this.$settings.focus();
}
/**
* #switchTab switches the active tab in the settings modal.
* @param {string} tabName
*/
#switchTab(tabName) {
this.$settingsTabs.forEach(($tab) => {
const isActive = $tab.dataset.tab === tabName;
$tab.classList.toggle('active', isActive);
$tab.setAttribute('aria-selected', String(isActive));
});
this.$settingsPanels.forEach(($panel) => {
const isActive = $panel.dataset.tabPanel === tabName;
$panel.classList.toggle('active', isActive);
$panel.hidden = !isActive;
});
}
/**
* #saveSystemMessage saves the textarea value to localStorage.
*/
#saveSystemMessage() {
const value = this.$systemMessageInput.value;
localStorage.setItem(SYSTEM_MESSAGE_KEY, value);
// Brief visual feedback on the save button.
this.$saveSystemMessage.replaceChildren(this.#icon('check'));
this.$saveSystemMessage.classList.add('settings-save-btn--success');
setTimeout(() => {
this.$saveSystemMessage.textContent = 'Save';
this.$saveSystemMessage.classList.remove('settings-save-btn--success');
}, 1500);
}
/**
* #loadSystemMessage reads from localStorage and populates the textarea.
*/
#loadSystemMessage() {
const stored = localStorage.getItem(SYSTEM_MESSAGE_KEY);
this.$systemMessageInput.value = stored || '';
}
// ====================
// RENDER: SELECTS
// ====================

View File

@@ -2,5 +2,6 @@
<body>
{{ template "main" . }}
{{ template "templates" . }}
{{ template "modal/settings" . }}
</body>
{{ end }}

View File

@@ -1,5 +1,14 @@
{{ define "footer/toolbar" }}
<div class="footer__toolbar">
<button
type="button"
class="footer__toolbar-btn"
id="settings"
aria-label="Settings"
>
<svg class="icon"><use href="/static/icons.svg#settings"></use></svg>
</button>
<div class="footer__toolbar-spacer"></div>
<button
type="button"
class="footer__toolbar-btn"
@@ -8,17 +17,6 @@
>
<svg class="icon"><use href="/static/icons.svg#reset"></use></svg>
</button>
<div class="footer__toolbar-spacer"></div>
<select id="model" class="footer__select" aria-label="Model">
<option value="" disabled selected>
Loading...
</option>
</select>
<select id="voice" class="footer__select" aria-label="Voice">
<option value="" disabled selected>
Loading...
</option>
</select>
<button
type="button"
class="footer__toolbar-btn"

View File

@@ -0,0 +1,83 @@
{{ define "modal/settings" }}
<div class="settings-overlay" id="settings-overlay">
<div class="settings-panel" role="dialog" aria-modal="true"
aria-labelledby="settings-title">
<div class="settings-panel__header">
<h2 class="settings-panel__title" id="settings-title">Settings</h2>
<button
type="button"
class="footer__toolbar-btn"
id="settings-close"
aria-label="Close settings"
>
<svg class="icon"><use href="/static/icons.svg#close"></use></svg>
</button>
</div>
<div class="settings-tabs" role="tablist">
<button
type="button"
class="settings-tab active"
role="tab"
data-tab="model-voice"
aria-selected="true"
aria-controls="panel-model-voice"
>Model &amp; Voice</button>
<button
type="button"
class="settings-tab"
role="tab"
data-tab="system-message"
aria-selected="false"
aria-controls="panel-system-message"
>System Message</button>
</div>
<div class="settings-tab-panels">
<div
class="settings-tab-panel active"
role="tabpanel"
data-tab-panel="model-voice"
id="panel-model-voice"
aria-labelledby="tab-model-voice"
>
<label class="settings-label" for="model">Model</label>
<select id="model" class="settings-select" aria-label="Model">
<option value="" disabled selected>Loading...</option>
</select>
<label class="settings-label" for="voice">Voice</label>
<select id="voice" class="settings-select" aria-label="Voice">
<option value="" disabled selected>Loading...</option>
</select>
</div>
<div
class="settings-tab-panel"
role="tabpanel"
data-tab-panel="system-message"
id="panel-system-message"
aria-labelledby="tab-system-message"
hidden
>
<label class="settings-label" for="system-message-input">
System Message
</label>
<textarea
id="system-message-input"
class="settings-textarea"
rows="8"
placeholder="Enter system message..."
></textarea>
<div class="settings-save-row">
<button
type="button"
class="settings-save-btn"
id="save-system-message"
>Save</button>
</div>
</div>
</div>
</div>
</div>
{{ end }}

View File

@@ -42,7 +42,7 @@ func NewDCESecurity(domain Domain, id uint32) (UUID, error) {
// NewDCEPerson returns a DCE Security (Version 2) UUID in the person
// domain with the id returned by os.Getuid.
//
// NewDCESecurity(Person, uint32(os.Getuid()))
// NewDCESecurity(Person, uint32(os.Getuid()))
func NewDCEPerson() (UUID, error) {
return NewDCESecurity(Person, uint32(os.Getuid()))
}
@@ -50,7 +50,7 @@ func NewDCEPerson() (UUID, error) {
// NewDCEGroup returns a DCE Security (Version 2) UUID in the group
// domain with the id returned by os.Getgid.
//
// NewDCESecurity(Group, uint32(os.Getgid()))
// NewDCESecurity(Group, uint32(os.Getgid()))
func NewDCEGroup() (UUID, error) {
return NewDCESecurity(Group, uint32(os.Getgid()))
}

View File

@@ -45,7 +45,7 @@ func NewHash(h hash.Hash, space UUID, data []byte, version int) UUID {
// NewMD5 returns a new MD5 (Version 3) UUID based on the
// supplied name space and data. It is the same as calling:
//
// NewHash(md5.New(), space, data, 3)
// NewHash(md5.New(), space, data, 3)
func NewMD5(space UUID, data []byte) UUID {
return NewHash(md5.New(), space, data, 3)
}
@@ -53,7 +53,7 @@ func NewMD5(space UUID, data []byte) UUID {
// NewSHA1 returns a new SHA1 (Version 5) UUID based on the
// supplied name space and data. It is the same as calling:
//
// NewHash(sha1.New(), space, data, 5)
// NewHash(sha1.New(), space, data, 5)
func NewSHA1(space UUID, data []byte) UUID {
return NewHash(sha1.New(), space, data, 5)
}

View File

@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build js
// +build js
package uuid

View File

@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build !js
// +build !js
package uuid

View File

@@ -17,15 +17,14 @@ var jsonNull = []byte("null")
// NullUUID implements the SQL driver.Scanner interface so
// it can be used as a scan destination:
//
// var u uuid.NullUUID
// err := db.QueryRow("SELECT name FROM foo WHERE id=?", id).Scan(&u)
// ...
// if u.Valid {
// // use u.UUID
// } else {
// // NULL value
// }
//
// var u uuid.NullUUID
// err := db.QueryRow("SELECT name FROM foo WHERE id=?", id).Scan(&u)
// ...
// if u.Valid {
// // use u.UUID
// } else {
// // NULL value
// }
type NullUUID struct {
UUID UUID
Valid bool // Valid is true if UUID is not NULL

View File

@@ -187,10 +187,12 @@ func Must(uuid UUID, err error) UUID {
}
// Validate returns an error if s is not a properly formatted UUID in one of the following formats:
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
//
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
//
// It returns an error if the format is invalid, otherwise nil.
func Validate(s string) error {
switch len(s) {

View File

@@ -9,7 +9,7 @@ import "io"
// New creates a new random UUID or panics. New is equivalent to
// the expression
//
// uuid.Must(uuid.NewRandom())
// uuid.Must(uuid.NewRandom())
func New() UUID {
return Must(NewRandom())
}
@@ -17,7 +17,7 @@ func New() UUID {
// NewString creates a new random UUID and returns it as a string or panics.
// NewString is equivalent to the expression
//
// uuid.New().String()
// uuid.New().String()
func NewString() string {
return Must(NewRandom()).String()
}
@@ -31,11 +31,11 @@ func NewString() string {
//
// A note about uniqueness derived from the UUID Wikipedia entry:
//
// Randomly generated UUIDs have 122 random bits. One's annual risk of being
// hit by a meteorite is estimated to be one chance in 17 billion, that
// means the probability is about 0.00000000006 (6 × 1011),
// equivalent to the odds of creating a few tens of trillions of UUIDs in a
// year and having one duplicate.
// Randomly generated UUIDs have 122 random bits. One's annual risk of being
// hit by a meteorite is estimated to be one chance in 17 billion, that
// means the probability is about 0.00000000006 (6 × 1011),
// equivalent to the odds of creating a few tens of trillions of UUIDs in a
// year and having one duplicate.
func NewRandom() (UUID, error) {
if !poolEnabled {
return NewRandomFromReader(rander)

8
vendor/gopkg.in/yaml.v3/apic.go generated vendored
View File

@@ -1,17 +1,17 @@
//
//
// Copyright (c) 2011-2019 Canonical Ltd
// Copyright (c) 2006-2010 Kirill Simonov
//
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is furnished to do
// so, subject to the following conditions:
//
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE

View File

@@ -162,10 +162,9 @@ func yaml_emitter_emit(emitter *yaml_emitter_t, event *yaml_event_t) bool {
// Check if we need to accumulate more events before emitting.
//
// We accumulate extra
// - 1 event for DOCUMENT-START
// - 2 events for SEQUENCE-START
// - 3 events for MAPPING-START
//
// - 1 event for DOCUMENT-START
// - 2 events for SEQUENCE-START
// - 3 events for MAPPING-START
func yaml_emitter_need_more_events(emitter *yaml_emitter_t) bool {
if emitter.events_head == len(emitter.events) {
return true
@@ -241,7 +240,7 @@ func yaml_emitter_increase_indent(emitter *yaml_emitter_t, flow, indentless bool
emitter.indent += 2
} else {
// Everything else aligns to the chosen indentation.
emitter.indent = emitter.best_indent*((emitter.indent+emitter.best_indent)/emitter.best_indent)
emitter.indent = emitter.best_indent * ((emitter.indent + emitter.best_indent) / emitter.best_indent)
}
}
return true

142
vendor/gopkg.in/yaml.v3/parserc.go generated vendored
View File

@@ -227,7 +227,8 @@ func yaml_parser_state_machine(parser *yaml_parser_t, event *yaml_event_t) bool
// Parse the production:
// stream ::= STREAM-START implicit_document? explicit_document* STREAM-END
// ************
//
// ************
func yaml_parser_parse_stream_start(parser *yaml_parser_t, event *yaml_event_t) bool {
token := peek_token(parser)
if token == nil {
@@ -249,9 +250,12 @@ func yaml_parser_parse_stream_start(parser *yaml_parser_t, event *yaml_event_t)
// Parse the productions:
// implicit_document ::= block_node DOCUMENT-END*
// *
//
// *
//
// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
// *************************
//
// *************************
func yaml_parser_parse_document_start(parser *yaml_parser_t, event *yaml_event_t, implicit bool) bool {
token := peek_token(parser)
@@ -356,8 +360,8 @@ func yaml_parser_parse_document_start(parser *yaml_parser_t, event *yaml_event_t
// Parse the productions:
// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
// ***********
//
// ***********
func yaml_parser_parse_document_content(parser *yaml_parser_t, event *yaml_event_t) bool {
token := peek_token(parser)
if token == nil {
@@ -379,9 +383,10 @@ func yaml_parser_parse_document_content(parser *yaml_parser_t, event *yaml_event
// Parse the productions:
// implicit_document ::= block_node DOCUMENT-END*
// *************
// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
//
// *************
//
// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
func yaml_parser_parse_document_end(parser *yaml_parser_t, event *yaml_event_t) bool {
token := peek_token(parser)
if token == nil {
@@ -428,30 +433,41 @@ func yaml_parser_set_event_comments(parser *yaml_parser_t, event *yaml_event_t)
// Parse the productions:
// block_node_or_indentless_sequence ::=
// ALIAS
// *****
// | properties (block_content | indentless_block_sequence)?
// ********** *
// | block_content | indentless_block_sequence
// *
//
// ALIAS
// *****
// | properties (block_content | indentless_block_sequence)?
// ********** *
// | block_content | indentless_block_sequence
// *
//
// block_node ::= ALIAS
// *****
// | properties block_content?
// ********** *
// | block_content
// *
//
// *****
// | properties block_content?
// ********** *
// | block_content
// *
//
// flow_node ::= ALIAS
// *****
// | properties flow_content?
// ********** *
// | flow_content
// *
//
// *****
// | properties flow_content?
// ********** *
// | flow_content
// *
//
// properties ::= TAG ANCHOR? | ANCHOR TAG?
// *************************
//
// *************************
//
// block_content ::= block_collection | flow_collection | SCALAR
// ******
//
// ******
//
// flow_content ::= flow_collection | SCALAR
// ******
//
// ******
func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, block, indentless_sequence bool) bool {
//defer trace("yaml_parser_parse_node", "block:", block, "indentless_sequence:", indentless_sequence)()
@@ -682,8 +698,8 @@ func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, block, i
// Parse the productions:
// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END
// ******************** *********** * *********
//
// ******************** *********** * *********
func yaml_parser_parse_block_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
if first {
token := peek_token(parser)
@@ -740,7 +756,8 @@ func yaml_parser_parse_block_sequence_entry(parser *yaml_parser_t, event *yaml_e
// Parse the productions:
// indentless_sequence ::= (BLOCK-ENTRY block_node?)+
// *********** *
//
// *********** *
func yaml_parser_parse_indentless_sequence_entry(parser *yaml_parser_t, event *yaml_event_t) bool {
token := peek_token(parser)
if token == nil {
@@ -805,14 +822,14 @@ func yaml_parser_split_stem_comment(parser *yaml_parser_t, stem_len int) {
// Parse the productions:
// block_mapping ::= BLOCK-MAPPING_START
// *******************
// ((KEY block_node_or_indentless_sequence?)?
// *** *
// (VALUE block_node_or_indentless_sequence?)?)*
//
// BLOCK-END
// *********
// *******************
// ((KEY block_node_or_indentless_sequence?)?
// *** *
// (VALUE block_node_or_indentless_sequence?)?)*
//
// BLOCK-END
// *********
func yaml_parser_parse_block_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
if first {
token := peek_token(parser)
@@ -881,13 +898,11 @@ func yaml_parser_parse_block_mapping_key(parser *yaml_parser_t, event *yaml_even
// Parse the productions:
// block_mapping ::= BLOCK-MAPPING_START
//
// ((KEY block_node_or_indentless_sequence?)?
//
// (VALUE block_node_or_indentless_sequence?)?)*
// ***** *
// BLOCK-END
//
// ((KEY block_node_or_indentless_sequence?)?
//
// (VALUE block_node_or_indentless_sequence?)?)*
// ***** *
// BLOCK-END
func yaml_parser_parse_block_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool {
token := peek_token(parser)
if token == nil {
@@ -915,16 +930,18 @@ func yaml_parser_parse_block_mapping_value(parser *yaml_parser_t, event *yaml_ev
// Parse the productions:
// flow_sequence ::= FLOW-SEQUENCE-START
// *******************
// (flow_sequence_entry FLOW-ENTRY)*
// * **********
// flow_sequence_entry?
// *
// FLOW-SEQUENCE-END
// *****************
// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
// *
//
// *******************
// (flow_sequence_entry FLOW-ENTRY)*
// * **********
// flow_sequence_entry?
// *
// FLOW-SEQUENCE-END
// *****************
//
// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
//
// *
func yaml_parser_parse_flow_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
if first {
token := peek_token(parser)
@@ -987,11 +1004,10 @@ func yaml_parser_parse_flow_sequence_entry(parser *yaml_parser_t, event *yaml_ev
return true
}
//
// Parse the productions:
// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
// *** *
//
// *** *
func yaml_parser_parse_flow_sequence_entry_mapping_key(parser *yaml_parser_t, event *yaml_event_t) bool {
token := peek_token(parser)
if token == nil {
@@ -1011,8 +1027,8 @@ func yaml_parser_parse_flow_sequence_entry_mapping_key(parser *yaml_parser_t, ev
// Parse the productions:
// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
// ***** *
//
// ***** *
func yaml_parser_parse_flow_sequence_entry_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool {
token := peek_token(parser)
if token == nil {
@@ -1035,8 +1051,8 @@ func yaml_parser_parse_flow_sequence_entry_mapping_value(parser *yaml_parser_t,
// Parse the productions:
// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
// *
//
// *
func yaml_parser_parse_flow_sequence_entry_mapping_end(parser *yaml_parser_t, event *yaml_event_t) bool {
token := peek_token(parser)
if token == nil {
@@ -1053,16 +1069,17 @@ func yaml_parser_parse_flow_sequence_entry_mapping_end(parser *yaml_parser_t, ev
// Parse the productions:
// flow_mapping ::= FLOW-MAPPING-START
// ******************
// (flow_mapping_entry FLOW-ENTRY)*
// * **********
// flow_mapping_entry?
// ******************
// FLOW-MAPPING-END
// ****************
// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
// * *** *
//
// ******************
// (flow_mapping_entry FLOW-ENTRY)*
// * **********
// flow_mapping_entry?
// ******************
// FLOW-MAPPING-END
// ****************
//
// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
// - *** *
func yaml_parser_parse_flow_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
if first {
token := peek_token(parser)
@@ -1128,8 +1145,7 @@ func yaml_parser_parse_flow_mapping_key(parser *yaml_parser_t, event *yaml_event
// Parse the productions:
// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
// * ***** *
//
// - ***** *
func yaml_parser_parse_flow_mapping_value(parser *yaml_parser_t, event *yaml_event_t, empty bool) bool {
token := peek_token(parser)
if token == nil {

8
vendor/gopkg.in/yaml.v3/readerc.go generated vendored
View File

@@ -1,17 +1,17 @@
//
//
// Copyright (c) 2011-2019 Canonical Ltd
// Copyright (c) 2006-2010 Kirill Simonov
//
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is furnished to do
// so, subject to the following conditions:
//
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE

42
vendor/gopkg.in/yaml.v3/scannerc.go generated vendored
View File

@@ -1614,11 +1614,11 @@ func yaml_parser_scan_to_next_token(parser *yaml_parser_t) bool {
// Scan a YAML-DIRECTIVE or TAG-DIRECTIVE token.
//
// Scope:
// %YAML 1.1 # a comment \n
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// %TAG !yaml! tag:yaml.org,2002: \n
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//
// %YAML 1.1 # a comment \n
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// %TAG !yaml! tag:yaml.org,2002: \n
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
func yaml_parser_scan_directive(parser *yaml_parser_t, token *yaml_token_t) bool {
// Eat '%'.
start_mark := parser.mark
@@ -1719,11 +1719,11 @@ func yaml_parser_scan_directive(parser *yaml_parser_t, token *yaml_token_t) bool
// Scan the directive name.
//
// Scope:
// %YAML 1.1 # a comment \n
// ^^^^
// %TAG !yaml! tag:yaml.org,2002: \n
// ^^^
//
// %YAML 1.1 # a comment \n
// ^^^^
// %TAG !yaml! tag:yaml.org,2002: \n
// ^^^
func yaml_parser_scan_directive_name(parser *yaml_parser_t, start_mark yaml_mark_t, name *[]byte) bool {
// Consume the directive name.
if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
@@ -1758,8 +1758,9 @@ func yaml_parser_scan_directive_name(parser *yaml_parser_t, start_mark yaml_mark
// Scan the value of VERSION-DIRECTIVE.
//
// Scope:
// %YAML 1.1 # a comment \n
// ^^^^^^
//
// %YAML 1.1 # a comment \n
// ^^^^^^
func yaml_parser_scan_version_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, major, minor *int8) bool {
// Eat whitespaces.
if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
@@ -1797,10 +1798,11 @@ const max_number_length = 2
// Scan the version number of VERSION-DIRECTIVE.
//
// Scope:
// %YAML 1.1 # a comment \n
// ^
// %YAML 1.1 # a comment \n
// ^
//
// %YAML 1.1 # a comment \n
// ^
// %YAML 1.1 # a comment \n
// ^
func yaml_parser_scan_version_directive_number(parser *yaml_parser_t, start_mark yaml_mark_t, number *int8) bool {
// Repeat while the next character is digit.
@@ -1834,9 +1836,9 @@ func yaml_parser_scan_version_directive_number(parser *yaml_parser_t, start_mark
// Scan the value of a TAG-DIRECTIVE token.
//
// Scope:
// %TAG !yaml! tag:yaml.org,2002: \n
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//
// %TAG !yaml! tag:yaml.org,2002: \n
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
func yaml_parser_scan_tag_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, handle, prefix *[]byte) bool {
var handle_value, prefix_value []byte
@@ -2847,7 +2849,7 @@ func yaml_parser_scan_line_comment(parser *yaml_parser_t, token_mark yaml_mark_t
continue
}
if parser.buffer[parser.buffer_pos+peek] == '#' {
seen := parser.mark.index+peek
seen := parser.mark.index + peek
for {
if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
return false
@@ -2876,7 +2878,7 @@ func yaml_parser_scan_line_comment(parser *yaml_parser_t, token_mark yaml_mark_t
parser.comments = append(parser.comments, yaml_comment_t{
token_mark: token_mark,
start_mark: start_mark,
line: text,
line: text,
})
}
return true
@@ -2910,7 +2912,7 @@ func yaml_parser_scan_comments(parser *yaml_parser_t, scan_mark yaml_mark_t) boo
// the foot is the line below it.
var foot_line = -1
if scan_mark.line > 0 {
foot_line = parser.mark.line-parser.newlines+1
foot_line = parser.mark.line - parser.newlines + 1
if parser.newlines == 0 && parser.mark.column > 1 {
foot_line++
}
@@ -2996,7 +2998,7 @@ func yaml_parser_scan_comments(parser *yaml_parser_t, scan_mark yaml_mark_t) boo
recent_empty = false
// Consume until after the consumed comment line.
seen := parser.mark.index+peek
seen := parser.mark.index + peek
for {
if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
return false

8
vendor/gopkg.in/yaml.v3/writerc.go generated vendored
View File

@@ -1,17 +1,17 @@
//
//
// Copyright (c) 2011-2019 Canonical Ltd
// Copyright (c) 2006-2010 Kirill Simonov
//
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is furnished to do
// so, subject to the following conditions:
//
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE

75
vendor/gopkg.in/yaml.v3/yaml.go generated vendored
View File

@@ -17,8 +17,7 @@
//
// Source code and other details for the project are available at GitHub:
//
// https://github.com/go-yaml/yaml
//
// https://github.com/go-yaml/yaml
package yaml
import (
@@ -75,16 +74,15 @@ type Marshaler interface {
//
// For example:
//
// type T struct {
// F int `yaml:"a,omitempty"`
// B int
// }
// var t T
// yaml.Unmarshal([]byte("a: 1\nb: 2"), &t)
// type T struct {
// F int `yaml:"a,omitempty"`
// B int
// }
// var t T
// yaml.Unmarshal([]byte("a: 1\nb: 2"), &t)
//
// See the documentation of Marshal for the format of tags and a list of
// supported tag options.
//
func Unmarshal(in []byte, out interface{}) (err error) {
return unmarshal(in, out, false)
}
@@ -185,36 +183,35 @@ func unmarshal(in []byte, out interface{}, strict bool) (err error) {
//
// The field tag format accepted is:
//
// `(...) yaml:"[<key>][,<flag1>[,<flag2>]]" (...)`
// `(...) yaml:"[<key>][,<flag1>[,<flag2>]]" (...)`
//
// The following flags are currently supported:
//
// omitempty Only include the field if it's not set to the zero
// value for the type or to empty slices or maps.
// Zero valued structs will be omitted if all their public
// fields are zero, unless they implement an IsZero
// method (see the IsZeroer interface type), in which
// case the field will be excluded if IsZero returns true.
// omitempty Only include the field if it's not set to the zero
// value for the type or to empty slices or maps.
// Zero valued structs will be omitted if all their public
// fields are zero, unless they implement an IsZero
// method (see the IsZeroer interface type), in which
// case the field will be excluded if IsZero returns true.
//
// flow Marshal using a flow style (useful for structs,
// sequences and maps).
// flow Marshal using a flow style (useful for structs,
// sequences and maps).
//
// inline Inline the field, which must be a struct or a map,
// causing all of its fields or keys to be processed as if
// they were part of the outer struct. For maps, keys must
// not conflict with the yaml keys of other struct fields.
// inline Inline the field, which must be a struct or a map,
// causing all of its fields or keys to be processed as if
// they were part of the outer struct. For maps, keys must
// not conflict with the yaml keys of other struct fields.
//
// In addition, if the key is "-", the field is ignored.
//
// For example:
//
// type T struct {
// F int `yaml:"a,omitempty"`
// B int
// }
// yaml.Marshal(&T{B: 2}) // Returns "b: 2\n"
// yaml.Marshal(&T{F: 1}} // Returns "a: 1\nb: 0\n"
//
// type T struct {
// F int `yaml:"a,omitempty"`
// B int
// }
// yaml.Marshal(&T{B: 2}) // Returns "b: 2\n"
// yaml.Marshal(&T{F: 1}} // Returns "a: 1\nb: 0\n"
func Marshal(in interface{}) (out []byte, err error) {
defer handleErr(&err)
e := newEncoder()
@@ -358,22 +355,21 @@ const (
//
// For example:
//
// var person struct {
// Name string
// Address yaml.Node
// }
// err := yaml.Unmarshal(data, &person)
//
// var person struct {
// Name string
// Address yaml.Node
// }
// err := yaml.Unmarshal(data, &person)
//
// Or by itself:
//
// var person Node
// err := yaml.Unmarshal(data, &person)
//
// var person Node
// err := yaml.Unmarshal(data, &person)
type Node struct {
// Kind defines whether the node is a document, a mapping, a sequence,
// a scalar value, or an alias to another node. The specific data type of
// scalar nodes may be obtained via the ShortTag and LongTag methods.
Kind Kind
Kind Kind
// Style allows customizing the apperance of the node in the tree.
Style Style
@@ -421,7 +417,6 @@ func (n *Node) IsZero() bool {
n.HeadComment == "" && n.LineComment == "" && n.FootComment == "" && n.Line == 0 && n.Column == 0
}
// LongTag returns the long form of the tag that indicates the data type for
// the node. If the Tag field isn't explicitly defined, one will be computed
// based on the node properties.

10
vendor/gopkg.in/yaml.v3/yamlh.go generated vendored
View File

@@ -438,7 +438,9 @@ type yaml_document_t struct {
// The number of written bytes should be set to the size_read variable.
//
// [in,out] data A pointer to an application data specified by
// yaml_parser_set_input().
//
// yaml_parser_set_input().
//
// [out] buffer The buffer to write the data from the source.
// [in] size The size of the buffer.
// [out] size_read The actual number of bytes read from the source.
@@ -639,7 +641,6 @@ type yaml_parser_t struct {
}
type yaml_comment_t struct {
scan_mark yaml_mark_t // Position where scanning for comments started
token_mark yaml_mark_t // Position after which tokens will be associated with this comment
start_mark yaml_mark_t // Position of '#' comment mark
@@ -659,13 +660,14 @@ type yaml_comment_t struct {
// @a buffer to the output.
//
// @param[in,out] data A pointer to an application data specified by
// yaml_emitter_set_output().
//
// yaml_emitter_set_output().
//
// @param[in] buffer The buffer with bytes to be written.
// @param[in] size The size of the buffer.
//
// @returns On success, the handler should return @c 1. If the handler failed,
// the returned value should be @c 0.
//
type yaml_write_handler_t func(emitter *yaml_emitter_t, buffer []byte) error
type yaml_emitter_state_t int

View File

@@ -1,17 +1,17 @@
//
//
// Copyright (c) 2011-2019 Canonical Ltd
// Copyright (c) 2006-2010 Kirill Simonov
//
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is furnished to do
// so, subject to the following conditions:
//
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -137,8 +137,8 @@ func is_crlf(b []byte, i int) bool {
func is_breakz(b []byte, i int) bool {
//return is_break(b, i) || is_z(b, i)
return (
// is_break:
b[i] == '\r' || // CR (#xD)
// is_break:
b[i] == '\r' || // CR (#xD)
b[i] == '\n' || // LF (#xA)
b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
@@ -151,8 +151,8 @@ func is_breakz(b []byte, i int) bool {
func is_spacez(b []byte, i int) bool {
//return is_space(b, i) || is_breakz(b, i)
return (
// is_space:
b[i] == ' ' ||
// is_space:
b[i] == ' ' ||
// is_breakz:
b[i] == '\r' || // CR (#xD)
b[i] == '\n' || // LF (#xA)
@@ -166,8 +166,8 @@ func is_spacez(b []byte, i int) bool {
func is_blankz(b []byte, i int) bool {
//return is_blank(b, i) || is_breakz(b, i)
return (
// is_blank:
b[i] == ' ' || b[i] == '\t' ||
// is_blank:
b[i] == ' ' || b[i] == '\t' ||
// is_breakz:
b[i] == '\r' || // CR (#xD)
b[i] == '\n' || // LF (#xA)