Compare commits
9 Commits
f04cc2c61e
...
492815c8fc
| Author | SHA1 | Date | |
|---|---|---|---|
|
492815c8fc
|
|||
|
aacf1b1d47
|
|||
|
49d7cb12bb
|
|||
|
fdf845d0bd
|
|||
|
75fc6f1c37
|
|||
|
8a8437634a
|
|||
|
e78b410a6a
|
|||
|
bf44e827e8
|
|||
|
8386af0420
|
@@ -1381,7 +1381,7 @@ struct mpd_client
|
|||||||
|
|
||||||
// Protocol:
|
// Protocol:
|
||||||
|
|
||||||
bool got_hello; ///< Got the OK MPD hello message
|
char *got_hello; ///< Version from OK MPD hello message
|
||||||
|
|
||||||
bool idling; ///< Sent idle as the last command
|
bool idling; ///< Sent idle as the last command
|
||||||
unsigned idling_subsystems; ///< Subsystems we're idling for
|
unsigned idling_subsystems; ///< Subsystems we're idling for
|
||||||
@@ -1482,7 +1482,7 @@ mpd_client_reset (struct mpd_client *self)
|
|||||||
str_reset (&self->read_buffer);
|
str_reset (&self->read_buffer);
|
||||||
str_reset (&self->write_buffer);
|
str_reset (&self->write_buffer);
|
||||||
|
|
||||||
self->got_hello = false;
|
cstr_set (&self->got_hello, NULL);
|
||||||
self->idling = false;
|
self->idling = false;
|
||||||
self->idling_subsystems = 0;
|
self->idling_subsystems = 0;
|
||||||
self->in_list = false;
|
self->in_list = false;
|
||||||
@@ -1549,7 +1549,8 @@ mpd_client_parse_hello (struct mpd_client *self, const char *line)
|
|||||||
|
|
||||||
// TODO: call "on_connected" now. We should however also set up a timer
|
// TODO: call "on_connected" now. We should however also set up a timer
|
||||||
// so that we don't wait on this message forever.
|
// so that we don't wait on this message forever.
|
||||||
return self->got_hello = true;
|
cstr_set (&self->got_hello, xstrdup (line + sizeof hello - 1));
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
@@ -1634,30 +1635,30 @@ mpd_client_on_ready (const struct pollfd *pfd, void *user_data)
|
|||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
||||||
static bool
|
|
||||||
mpd_client_must_quote_char (char c)
|
|
||||||
{
|
|
||||||
return (unsigned char) c <= ' ' || c == '"' || c == '\'';
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
mpd_client_must_quote (const char *s)
|
mpd_client_must_quote (const char *s)
|
||||||
{
|
{
|
||||||
if (!*s)
|
if (!*s)
|
||||||
return true;
|
return true;
|
||||||
for (; *s; s++)
|
for (; *s; s++)
|
||||||
if (mpd_client_must_quote_char (*s))
|
if ((unsigned char) *s <= ' ' || *s == '"' || *s == '\'')
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
mpd_client_must_escape_in_quote (char c)
|
||||||
|
{
|
||||||
|
return c == '"' || c == '\'' || c == '\\';
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mpd_client_quote (const char *s, struct str *output)
|
mpd_client_quote (const char *s, struct str *output)
|
||||||
{
|
{
|
||||||
str_append_c (output, '"');
|
str_append_c (output, '"');
|
||||||
for (; *s; s++)
|
for (; *s; s++)
|
||||||
{
|
{
|
||||||
if (mpd_client_must_quote_char (*s))
|
if (mpd_client_must_escape_in_quote (*s))
|
||||||
str_append_c (output, '\\');
|
str_append_c (output, '\\');
|
||||||
str_append_c (output, *s);
|
str_append_c (output, *s);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,12 +24,12 @@
|
|||||||
// It is surprisingly hard to find a good library to handle Unicode shenanigans,
|
// It is surprisingly hard to find a good library to handle Unicode shenanigans,
|
||||||
// and there's enough of those for it to be impractical to reimplement them.
|
// and there's enough of those for it to be impractical to reimplement them.
|
||||||
//
|
//
|
||||||
// GLib ICU libunistring utf8proc
|
// GLib ICU libunistring utf8proc libgrapheme
|
||||||
// Decently sized . . x x
|
// Decently sized . . x x x
|
||||||
// Grapheme breaks . x . x
|
// Grapheme breaks . x . x x
|
||||||
// Character width x . x x
|
// Character width x . x x .
|
||||||
// Locale handling . . x .
|
// Locale handling . . x . .
|
||||||
// Liberal license . x . x
|
// Liberal license . x . x x
|
||||||
//
|
//
|
||||||
// Also note that the ICU API is icky and uses UTF-16 for its primary encoding.
|
// Also note that the ICU API is icky and uses UTF-16 for its primary encoding.
|
||||||
//
|
//
|
||||||
@@ -205,8 +205,8 @@ static void
|
|||||||
line_editor_start (struct line_editor *self, char prompt)
|
line_editor_start (struct line_editor *self, char prompt)
|
||||||
{
|
{
|
||||||
self->alloc = 16;
|
self->alloc = 16;
|
||||||
self->line = xcalloc (sizeof *self->line, self->alloc);
|
self->line = xcalloc (self->alloc, sizeof *self->line);
|
||||||
self->w = xcalloc (sizeof *self->w, self->alloc);
|
self->w = xcalloc (self->alloc, sizeof *self->w);
|
||||||
self->len = 0;
|
self->len = 0;
|
||||||
self->point = 0;
|
self->point = 0;
|
||||||
self->prompt = prompt;
|
self->prompt = prompt;
|
||||||
|
|||||||
19
liberty.c
19
liberty.c
@@ -292,7 +292,8 @@ xreallocarray (void *o, size_t n, size_t m)
|
|||||||
static char *
|
static char *
|
||||||
xstrdup (const char *s)
|
xstrdup (const char *s)
|
||||||
{
|
{
|
||||||
return strcpy (xmalloc (strlen (s) + 1), s);
|
size_t len = strlen (s) + 1;
|
||||||
|
return memcpy (xmalloc (len), s, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
@@ -315,7 +316,7 @@ xstrndup (const char *s, size_t n)
|
|||||||
#define ARRAY(type, name) type *name; size_t name ## _len, name ## _alloc;
|
#define ARRAY(type, name) type *name; size_t name ## _len, name ## _alloc;
|
||||||
#define ARRAY_INIT_SIZED(a, n) \
|
#define ARRAY_INIT_SIZED(a, n) \
|
||||||
BLOCK_START \
|
BLOCK_START \
|
||||||
(a) = xcalloc (sizeof *(a), (a ## _alloc) = (n)); \
|
(a) = xcalloc ((a ## _alloc) = (n), sizeof *(a)); \
|
||||||
(a ## _len) = 0; \
|
(a ## _len) = 0; \
|
||||||
BLOCK_END
|
BLOCK_END
|
||||||
#define ARRAY_INIT(a) ARRAY_INIT_SIZED (a, 16)
|
#define ARRAY_INIT(a) ARRAY_INIT_SIZED (a, 16)
|
||||||
@@ -397,7 +398,7 @@ strv_make (void)
|
|||||||
struct strv self;
|
struct strv self;
|
||||||
self.alloc = 4;
|
self.alloc = 4;
|
||||||
self.len = 0;
|
self.len = 0;
|
||||||
self.vector = xcalloc (sizeof *self.vector, self.alloc);
|
self.vector = xcalloc (self.alloc, sizeof *self.vector);
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4500,7 +4501,7 @@ struct config_item
|
|||||||
}
|
}
|
||||||
value; ///< The value of this item
|
value; ///< The value of this item
|
||||||
|
|
||||||
struct config_schema *schema; ///< Schema describing this value
|
const struct config_schema *schema; ///< Schema describing this value
|
||||||
void *user_data; ///< User value attached by schema owner
|
void *user_data; ///< User value attached by schema owner
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -4652,7 +4653,7 @@ config_item_object (void)
|
|||||||
|
|
||||||
static bool
|
static bool
|
||||||
config_schema_accepts_type
|
config_schema_accepts_type
|
||||||
(struct config_schema *self, enum config_item_type type)
|
(const struct config_schema *self, enum config_item_type type)
|
||||||
{
|
{
|
||||||
if (self->type == type)
|
if (self->type == type)
|
||||||
return true;
|
return true;
|
||||||
@@ -4665,7 +4666,7 @@ config_schema_accepts_type
|
|||||||
|
|
||||||
static bool
|
static bool
|
||||||
config_item_validate_by_schema (struct config_item *self,
|
config_item_validate_by_schema (struct config_item *self,
|
||||||
struct config_schema *schema, struct error **e)
|
const struct config_schema *schema, struct error **e)
|
||||||
{
|
{
|
||||||
struct error *error = NULL;
|
struct error *error = NULL;
|
||||||
if (!config_schema_accepts_type (schema, self->type))
|
if (!config_schema_accepts_type (schema, self->type))
|
||||||
@@ -4686,7 +4687,7 @@ static bool
|
|||||||
config_item_set_from (struct config_item *self, struct config_item *source,
|
config_item_set_from (struct config_item *self, struct config_item *source,
|
||||||
struct error **e)
|
struct error **e)
|
||||||
{
|
{
|
||||||
struct config_schema *schema = self->schema;
|
const struct config_schema *schema = self->schema;
|
||||||
if (!schema)
|
if (!schema)
|
||||||
{
|
{
|
||||||
// Easy, we don't know what this item is
|
// Easy, we don't know what this item is
|
||||||
@@ -5482,7 +5483,7 @@ end:
|
|||||||
|
|
||||||
/// "user_data" is passed to allow its immediate use in validation callbacks
|
/// "user_data" is passed to allow its immediate use in validation callbacks
|
||||||
static struct config_item *
|
static struct config_item *
|
||||||
config_schema_initialize_item (struct config_schema *schema,
|
config_schema_initialize_item (const struct config_schema *schema,
|
||||||
struct config_item *parent, void *user_data, struct error **warning,
|
struct config_item *parent, void *user_data, struct error **warning,
|
||||||
struct error **e)
|
struct error **e)
|
||||||
{
|
{
|
||||||
@@ -5539,7 +5540,7 @@ keep_current:
|
|||||||
/// Assign schemas and user_data to multiple items at once;
|
/// Assign schemas and user_data to multiple items at once;
|
||||||
/// feel free to copy over and modify to suit your particular needs
|
/// feel free to copy over and modify to suit your particular needs
|
||||||
static void
|
static void
|
||||||
config_schema_apply_to_object (struct config_schema *schema_array,
|
config_schema_apply_to_object (const struct config_schema *schema_array,
|
||||||
struct config_item *object, void *user_data)
|
struct config_item *object, void *user_data)
|
||||||
{
|
{
|
||||||
while (schema_array->name)
|
while (schema_array->name)
|
||||||
|
|||||||
@@ -636,7 +636,7 @@ test_config_validate_nonnegative
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct config_schema g_config_test[] =
|
static const struct config_schema g_config_test[] =
|
||||||
{
|
{
|
||||||
{ .name = "foo",
|
{ .name = "foo",
|
||||||
.comment = "baz",
|
.comment = "baz",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# lxdrgen-go.awk: Go backend for lxdrgen.awk.
|
# lxdrgen-go.awk: Go backend for lxdrgen.awk.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2022, Přemysl Eric Janouch <p@janouch.name>
|
# Copyright (c) 2022 - 2024, Přemysl Eric Janouch <p@janouch.name>
|
||||||
# SPDX-License-Identifier: 0BSD
|
# SPDX-License-Identifier: 0BSD
|
||||||
#
|
#
|
||||||
# This backend also enables proxying to other endpoints using JSON.
|
# This backend also enables proxying to other endpoints using JSON.
|
||||||
@@ -145,7 +145,7 @@ function codegen_begin( funcname) {
|
|||||||
print "// " funcname " tries to serialize a string value,"
|
print "// " funcname " tries to serialize a string value,"
|
||||||
print "// appending it to the end of a byte stream."
|
print "// appending it to the end of a byte stream."
|
||||||
print "func " funcname "(data []byte, s string) ([]byte, bool) {"
|
print "func " funcname "(data []byte, s string) ([]byte, bool) {"
|
||||||
print "\tif len(s) > math.MaxUint32 {"
|
print "\tif int64(len(s)) > math.MaxUint32 {"
|
||||||
print "\t\treturn nil, false"
|
print "\t\treturn nil, false"
|
||||||
print "\t}"
|
print "\t}"
|
||||||
print "\tdata = binary.BigEndian.AppendUint32(data, uint32(len(s)))"
|
print "\tdata = binary.BigEndian.AppendUint32(data, uint32(len(s)))"
|
||||||
@@ -301,9 +301,11 @@ function codegen_marshal(type, f, marshal) {
|
|||||||
"\t}\n"
|
"\t}\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
function codegen_struct_field_marshal(d, cg, camel, f, marshal) {
|
function codegen_struct_field_marshal(d, cg, isaccessor, camel, f, marshal) {
|
||||||
camel = snaketocamel(d["name"])
|
camel = snaketocamel(d["name"])
|
||||||
f = "s." camel
|
f = "s." camel
|
||||||
|
if (isaccessor)
|
||||||
|
f = f "()"
|
||||||
if (!d["isarray"]) {
|
if (!d["isarray"]) {
|
||||||
append(cg, "marshal",
|
append(cg, "marshal",
|
||||||
"\tb = append(b, `,\"" decapitalize(camel) "\":`...)\n" \
|
"\tb = append(b, `,\"" decapitalize(camel) "\":`...)\n" \
|
||||||
@@ -333,7 +335,7 @@ function codegen_struct_field_marshal(d, cg, camel, f, marshal) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function codegen_struct_field(d, cg, camel, f, serialize, deserialize) {
|
function codegen_struct_field(d, cg, camel, f, serialize, deserialize) {
|
||||||
codegen_struct_field_marshal(d, cg)
|
codegen_struct_field_marshal(d, cg, 0)
|
||||||
|
|
||||||
camel = snaketocamel(d["name"])
|
camel = snaketocamel(d["name"])
|
||||||
f = "s." camel
|
f = "s." camel
|
||||||
@@ -384,15 +386,11 @@ function codegen_struct_field(d, cg, camel, f, serialize, deserialize) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function codegen_struct_tag(d, cg, camel, f) {
|
function codegen_struct_tag(d, cg) {
|
||||||
codegen_struct_field_marshal(d, cg)
|
codegen_struct_field_marshal(d, cg, 1)
|
||||||
|
|
||||||
camel = snaketocamel(d["name"])
|
# Do not serialize or deserialize here,
|
||||||
f = "s." camel
|
# that is already done by the containing union.
|
||||||
append(cg, "fields", "\t" camel " " CodegenGoType[d["type"]] \
|
|
||||||
" `json:\"" decapitalize(camel) "\"`\n")
|
|
||||||
append(cg, "serialize", sprintf(CodegenSerialize[d["type"]], f))
|
|
||||||
# Do not deserialize here, that is already done by the containing union.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function codegen_struct(name, cg, gotype) {
|
function codegen_struct(name, cg, gotype) {
|
||||||
@@ -450,13 +448,18 @@ function codegen_union_struct(name, casename, cg, scg, structname, init) {
|
|||||||
structname = name snaketocamel(casename)
|
structname = name snaketocamel(casename)
|
||||||
codegen_struct(structname, scg)
|
codegen_struct(structname, scg)
|
||||||
|
|
||||||
init = CodegenGoType[structname] "{" cg["tagname"] \
|
print "func (u *" CodegenGoType[structname] ") " cg["tagname"] "() " \
|
||||||
": " decapitalize(cg["tagname"]) "}"
|
CodegenGoType[cg["tagtype"]] " {"
|
||||||
|
print "\treturn " CodegenGoType[cg["tagtype"]] snaketocamel(casename)
|
||||||
|
print "}"
|
||||||
|
print ""
|
||||||
|
|
||||||
|
init = CodegenGoType[structname] "{}"
|
||||||
append(cg, "unmarshal",
|
append(cg, "unmarshal",
|
||||||
"\tcase " CodegenGoType[cg["tagtype"]] snaketocamel(casename) ":\n" \
|
"\tcase " CodegenGoType[cg["tagtype"]] snaketocamel(casename) ":\n" \
|
||||||
"\t\ts := " init "\n" \
|
"\t\ts := " init "\n" \
|
||||||
"\t\terr = json.Unmarshal(data, &s)\n" \
|
"\t\terr = json.Unmarshal(data, &s)\n" \
|
||||||
"\t\tu.Interface = &s\n")
|
"\t\tu.Variant = &s\n")
|
||||||
append(cg, "serialize",
|
append(cg, "serialize",
|
||||||
"\tcase *" CodegenGoType[structname] ":\n" \
|
"\tcase *" CodegenGoType[structname] ":\n" \
|
||||||
indent(sprintf(CodegenSerialize[structname], "union")))
|
indent(sprintf(CodegenSerialize[structname], "union")))
|
||||||
@@ -464,20 +467,23 @@ function codegen_union_struct(name, casename, cg, scg, structname, init) {
|
|||||||
"\tcase " CodegenGoType[cg["tagtype"]] snaketocamel(casename) ":\n" \
|
"\tcase " CodegenGoType[cg["tagtype"]] snaketocamel(casename) ":\n" \
|
||||||
"\t\ts := " init "\n" \
|
"\t\ts := " init "\n" \
|
||||||
indent(sprintf(CodegenDeserialize[structname], "s")) \
|
indent(sprintf(CodegenDeserialize[structname], "s")) \
|
||||||
"\t\tu.Interface = &s\n")
|
"\t\tu.Variant = &s\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
function codegen_union(name, cg, exhaustive, gotype, tagvar) {
|
function codegen_union(name, cg, exhaustive, gotype, tagvar) {
|
||||||
gotype = PrefixCamel name
|
gotype = PrefixCamel name
|
||||||
|
# This must be a struct, so that UnmarshalJSON can create concrete types.
|
||||||
print "type " gotype " struct {"
|
print "type " gotype " struct {"
|
||||||
print "\tInterface any"
|
print "\tVariant interface {"
|
||||||
|
print "\t\t" cg["tagname"] "() " CodegenGoType[cg["tagtype"]]
|
||||||
|
print "\t}"
|
||||||
print "}"
|
print "}"
|
||||||
print ""
|
print ""
|
||||||
|
|
||||||
# This cannot be a pointer method, it wouldn't work recursively.
|
# This cannot be a pointer method, it wouldn't work recursively.
|
||||||
CodegenIsMarshaler[name] = 1
|
CodegenIsMarshaler[name] = 1
|
||||||
print "func (u " gotype ") MarshalJSON() ([]byte, error) {"
|
print "func (u " gotype ") MarshalJSON() ([]byte, error) {"
|
||||||
print "\treturn u.Interface.(json.Marshaler).MarshalJSON()"
|
print "\treturn u.Variant.(json.Marshaler).MarshalJSON()"
|
||||||
print "}"
|
print "}"
|
||||||
print ""
|
print ""
|
||||||
|
|
||||||
@@ -499,13 +505,15 @@ function codegen_union(name, cg, exhaustive, gotype, tagvar) {
|
|||||||
print "}"
|
print "}"
|
||||||
print ""
|
print ""
|
||||||
|
|
||||||
# XXX: Consider changing the interface into an AppendTo/ConsumeFrom one,
|
# XXX: Consider rather testing the type for having an AppendTo method,
|
||||||
# that would eliminate these type case switches entirely.
|
# which would eliminate this type case switch entirely.
|
||||||
# On the other hand, it would make it possible to send unsuitable structs.
|
|
||||||
print "func (u *" gotype ") AppendTo(data []byte) ([]byte, bool) {"
|
print "func (u *" gotype ") AppendTo(data []byte) ([]byte, bool) {"
|
||||||
print "\tok := true"
|
print "\tok := true"
|
||||||
print "\tswitch union := u.Interface.(type) {"
|
print sprintf(CodegenSerialize[cg["tagtype"]],
|
||||||
|
"u.Variant." cg["tagname"] "()") \
|
||||||
|
"\tswitch union := u.Variant.(type) {"
|
||||||
print cg["serialize"] "\tdefault:"
|
print cg["serialize"] "\tdefault:"
|
||||||
|
print "\t\t_ = union"
|
||||||
print "\t\treturn nil, false"
|
print "\t\treturn nil, false"
|
||||||
print "\t}"
|
print "\t}"
|
||||||
print "\treturn data, ok"
|
print "\treturn data, ok"
|
||||||
|
|||||||
Reference in New Issue
Block a user