mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-29 05:40:27 -04:00
pod: rework the parser
Make a new body.h file with some functions to deal with pod and their body. Make the iter.h functions use mostly this. Rework the parser so that it only uses body.h functions. With the separation of pod+body, we can read and verify the pod once and then use the verified copy to handle the rest of the body safely. We do this because iter.h only works in pods in memory that doesn't change because it is vulnerable to modifications of the data after verifying it. The new parser is not vulnerable to this and will not cause invalid memory access when used on shared memory. There is however no need for atomic operations to read the headers, whever is read is either valid and useable of invalid and rejected. See #4822
This commit is contained in:
parent
e2c291d18e
commit
e317edcfb9
16 changed files with 826 additions and 380 deletions
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <spa/pod/parser.h>
|
||||
#include <spa/pod/iter.h>
|
||||
#include <spa/utils/string.h>
|
||||
#include <spa/debug/context.h>
|
||||
#include <spa/debug/types.h>
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#ifndef SPA_AUDIO_DSD_UTILS_H
|
||||
#define SPA_AUDIO_DSD_UTILS_H
|
||||
|
||||
#include <spa/pod/iter.h>
|
||||
#include <spa/pod/parser.h>
|
||||
#include <spa/pod/builder.h>
|
||||
#include <spa/param/format-utils.h>
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#define SPA_AUDIO_RAW_UTILS_H
|
||||
|
||||
#include <spa/pod/parser.h>
|
||||
#include <spa/pod/iter.h>
|
||||
#include <spa/pod/builder.h>
|
||||
#include <spa/param/audio/format.h>
|
||||
#include <spa/param/format-utils.h>
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include <spa/utils/dict.h>
|
||||
#include <spa/pod/builder.h>
|
||||
#include <spa/pod/iter.h>
|
||||
#include <spa/pod/parser.h>
|
||||
#include <spa/param/tag.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#ifndef SPA_VIDEO_DSP_UTILS_H
|
||||
#define SPA_VIDEO_DSP_UTILS_H
|
||||
|
||||
#include <spa/pod/iter.h>
|
||||
#include <spa/pod/parser.h>
|
||||
#include <spa/pod/builder.h>
|
||||
#include <spa/param/video/dsp.h>
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#ifndef SPA_VIDEO_RAW_UTILS_H
|
||||
#define SPA_VIDEO_RAW_UTILS_H
|
||||
|
||||
#include <spa/pod/iter.h>
|
||||
#include <spa/pod/parser.h>
|
||||
#include <spa/pod/builder.h>
|
||||
#include <spa/param/video/raw.h>
|
||||
|
|
|
|||
392
spa/include/spa/pod/body.h
Normal file
392
spa/include/spa/pod/body.h
Normal file
|
|
@ -0,0 +1,392 @@
|
|||
/* Simple Plugin API */
|
||||
/* SPDX-FileCopyrightText: Copyright © 2018 Wim Taymans */
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef SPA_POD_BODY_H
|
||||
#define SPA_POD_BODY_H
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <spa/pod/pod.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef SPA_API_POD_BODY
|
||||
#ifdef SPA_API_IMPL
|
||||
#define SPA_API_POD_BODY SPA_API_IMPL
|
||||
#else
|
||||
#define SPA_API_POD_BODY static inline
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \addtogroup spa_pod
|
||||
* \{
|
||||
*/
|
||||
|
||||
struct spa_pod_frame {
|
||||
struct spa_pod pod;
|
||||
struct spa_pod_frame *parent;
|
||||
uint32_t offset;
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
SPA_API_POD_BODY uint32_t spa_pod_type_size(uint32_t type)
|
||||
{
|
||||
switch (type) {
|
||||
case SPA_TYPE_None:
|
||||
case SPA_TYPE_Bytes:
|
||||
case SPA_TYPE_Struct:
|
||||
case SPA_TYPE_Pod:
|
||||
return 0;
|
||||
case SPA_TYPE_String:
|
||||
return 1;
|
||||
case SPA_TYPE_Bool:
|
||||
case SPA_TYPE_Int:
|
||||
return sizeof(int32_t);
|
||||
case SPA_TYPE_Id:
|
||||
return sizeof(uint32_t);
|
||||
case SPA_TYPE_Long:
|
||||
return sizeof(int64_t);
|
||||
case SPA_TYPE_Float:
|
||||
return sizeof(float);
|
||||
case SPA_TYPE_Double:
|
||||
return sizeof(double);
|
||||
case SPA_TYPE_Rectangle:
|
||||
return sizeof(struct spa_rectangle);
|
||||
case SPA_TYPE_Fraction:
|
||||
return sizeof(struct spa_fraction);
|
||||
case SPA_TYPE_Bitmap:
|
||||
return sizeof(uint8_t);
|
||||
case SPA_TYPE_Array:
|
||||
return sizeof(struct spa_pod_array_body);
|
||||
case SPA_TYPE_Object:
|
||||
return sizeof(struct spa_pod_object_body);
|
||||
case SPA_TYPE_Sequence:
|
||||
return sizeof(struct spa_pod_sequence_body);
|
||||
case SPA_TYPE_Pointer:
|
||||
return sizeof(struct spa_pod_pointer_body);
|
||||
case SPA_TYPE_Fd:
|
||||
return sizeof(int64_t);
|
||||
case SPA_TYPE_Choice:
|
||||
return sizeof(struct spa_pod_choice_body);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPA_API_POD_BODY int spa_pod_body_from_data(void *data, size_t maxsize, off_t offset, size_t size,
|
||||
struct spa_pod *pod, const void **body)
|
||||
{
|
||||
if (offset < 0 || offset > (int64_t)UINT32_MAX)
|
||||
return -EINVAL;
|
||||
if (size < sizeof(struct spa_pod) ||
|
||||
size > maxsize ||
|
||||
maxsize - size < (uint32_t)offset)
|
||||
return -EINVAL;
|
||||
memcpy(pod, SPA_PTROFF(data, offset, void), sizeof(struct spa_pod));
|
||||
if (!SPA_POD_IS_VALID(pod))
|
||||
return -EINVAL;
|
||||
if (pod->size > size - sizeof(struct spa_pod))
|
||||
return -EINVAL;
|
||||
*body = SPA_PTROFF(data, offset + sizeof(struct spa_pod), void);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPA_API_POD_BODY int spa_pod_is_none(const struct spa_pod *pod)
|
||||
{
|
||||
return SPA_POD_CHECK_TYPE(pod, SPA_TYPE_None);
|
||||
}
|
||||
|
||||
SPA_API_POD_BODY int spa_pod_is_bool(const struct spa_pod *pod)
|
||||
{
|
||||
return SPA_POD_CHECK(pod, SPA_TYPE_Bool, sizeof(int32_t));
|
||||
}
|
||||
|
||||
SPA_API_POD_BODY int spa_pod_body_get_bool(const struct spa_pod *pod, const void *body, bool *value)
|
||||
{
|
||||
if (!spa_pod_is_bool(pod))
|
||||
return -EINVAL;
|
||||
*value = !!*((int32_t*)body);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPA_API_POD_BODY int spa_pod_is_id(const struct spa_pod *pod)
|
||||
{
|
||||
return SPA_POD_CHECK(pod, SPA_TYPE_Id, sizeof(uint32_t));
|
||||
}
|
||||
|
||||
SPA_API_POD_BODY int spa_pod_body_get_id(const struct spa_pod *pod, const void *body, uint32_t *value)
|
||||
{
|
||||
if (!spa_pod_is_id(pod))
|
||||
return -EINVAL;
|
||||
*value = *((uint32_t*)body);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPA_API_POD_BODY int spa_pod_is_int(const struct spa_pod *pod)
|
||||
{
|
||||
return SPA_POD_CHECK(pod, SPA_TYPE_Int, sizeof(int32_t));
|
||||
}
|
||||
|
||||
SPA_API_POD_BODY int spa_pod_body_get_int(const struct spa_pod *pod, const void *body, int32_t *value)
|
||||
{
|
||||
if (!spa_pod_is_int(pod))
|
||||
return -EINVAL;
|
||||
*value = *((int32_t*)body);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPA_API_POD_BODY int spa_pod_is_long(const struct spa_pod *pod)
|
||||
{
|
||||
return SPA_POD_CHECK(pod, SPA_TYPE_Long, sizeof(int64_t));
|
||||
}
|
||||
|
||||
SPA_API_POD_BODY int spa_pod_body_get_long(const struct spa_pod *pod, const void *body, int64_t *value)
|
||||
{
|
||||
if (!spa_pod_is_long(pod))
|
||||
return -EINVAL;
|
||||
*value = *((int64_t*)body);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPA_API_POD_BODY int spa_pod_is_float(const struct spa_pod *pod)
|
||||
{
|
||||
return SPA_POD_CHECK(pod, SPA_TYPE_Float, sizeof(float));
|
||||
}
|
||||
|
||||
SPA_API_POD_BODY int spa_pod_body_get_float(const struct spa_pod *pod, const void *body, float *value)
|
||||
{
|
||||
if (!spa_pod_is_float(pod))
|
||||
return -EINVAL;
|
||||
*value = *((float*)body);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPA_API_POD_BODY int spa_pod_is_double(const struct spa_pod *pod)
|
||||
{
|
||||
return SPA_POD_CHECK(pod, SPA_TYPE_Double, sizeof(double));
|
||||
}
|
||||
|
||||
SPA_API_POD_BODY int spa_pod_body_get_double(const struct spa_pod *pod, const void *body, double *value)
|
||||
{
|
||||
if (!spa_pod_is_double(pod))
|
||||
return -EINVAL;
|
||||
*value = *((double*)body);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPA_API_POD_BODY int spa_pod_is_string(const struct spa_pod *pod)
|
||||
{
|
||||
return SPA_POD_CHECK(pod, SPA_TYPE_String, 1);
|
||||
}
|
||||
|
||||
SPA_API_POD_BODY int spa_pod_body_get_string(const struct spa_pod *pod,
|
||||
const void *body, const char **value)
|
||||
{
|
||||
const char *s;
|
||||
if (!spa_pod_is_string(pod))
|
||||
return -EINVAL;
|
||||
s = (const char *)body;
|
||||
if (s[pod->size-1] != '\0')
|
||||
return -EINVAL;
|
||||
*value = s;
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPA_API_POD_BODY int spa_pod_body_copy_string(const struct spa_pod *pod, const void *body,
|
||||
size_t maxlen, char *dest)
|
||||
{
|
||||
const char *s;
|
||||
if (spa_pod_body_get_string(pod, body, &s) < 0 || maxlen < 1)
|
||||
return -EINVAL;
|
||||
strncpy(dest, s, maxlen-1);
|
||||
dest[maxlen-1]= '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPA_API_POD_BODY int spa_pod_is_bytes(const struct spa_pod *pod)
|
||||
{
|
||||
return SPA_POD_CHECK_TYPE(pod, SPA_TYPE_Bytes);
|
||||
}
|
||||
|
||||
SPA_API_POD_BODY int spa_pod_body_get_bytes(const struct spa_pod *pod, const void *body,
|
||||
const void **value, uint32_t *len)
|
||||
{
|
||||
if (!spa_pod_is_bytes(pod))
|
||||
return -EINVAL;
|
||||
*value = (const void *)body;
|
||||
*len = pod->size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPA_API_POD_BODY int spa_pod_is_pointer(const struct spa_pod *pod)
|
||||
{
|
||||
return SPA_POD_CHECK(pod, SPA_TYPE_Pointer, sizeof(struct spa_pod_pointer_body));
|
||||
}
|
||||
|
||||
SPA_API_POD_BODY int spa_pod_body_get_pointer(const struct spa_pod *pod, const void *body,
|
||||
uint32_t *type, const void **value)
|
||||
{
|
||||
if (!spa_pod_is_pointer(pod))
|
||||
return -EINVAL;
|
||||
*type = ((struct spa_pod_pointer_body*)body)->type;
|
||||
*value = ((struct spa_pod_pointer_body*)body)->value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPA_API_POD_BODY int spa_pod_is_fd(const struct spa_pod *pod)
|
||||
{
|
||||
return SPA_POD_CHECK(pod, SPA_TYPE_Fd, sizeof(int64_t));
|
||||
}
|
||||
|
||||
SPA_API_POD_BODY int spa_pod_body_get_fd(const struct spa_pod *pod, const void *body,
|
||||
int64_t *value)
|
||||
{
|
||||
if (!spa_pod_is_fd(pod))
|
||||
return -EINVAL;
|
||||
*value = *((int64_t*)body);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPA_API_POD_BODY int spa_pod_is_rectangle(const struct spa_pod *pod)
|
||||
{
|
||||
return SPA_POD_CHECK(pod, SPA_TYPE_Rectangle, sizeof(struct spa_rectangle));
|
||||
}
|
||||
|
||||
SPA_API_POD_BODY int spa_pod_body_get_rectangle(const struct spa_pod *pod, const void *body,
|
||||
struct spa_rectangle *value)
|
||||
{
|
||||
if (!spa_pod_is_rectangle(pod))
|
||||
return -EINVAL;
|
||||
*value = *((struct spa_rectangle*)body);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPA_API_POD_BODY int spa_pod_is_fraction(const struct spa_pod *pod)
|
||||
{
|
||||
return SPA_POD_CHECK(pod, SPA_TYPE_Fraction, sizeof(struct spa_fraction));
|
||||
}
|
||||
SPA_API_POD_BODY int spa_pod_body_get_fraction(const struct spa_pod *pod, const void *body,
|
||||
struct spa_fraction *value)
|
||||
{
|
||||
if (!spa_pod_is_fraction(pod))
|
||||
return -EINVAL;
|
||||
*value = *((struct spa_fraction*)body);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPA_API_POD_BODY int spa_pod_is_bitmap(const struct spa_pod *pod)
|
||||
{
|
||||
return SPA_POD_CHECK(pod, SPA_TYPE_Bitmap, sizeof(uint8_t));
|
||||
}
|
||||
|
||||
SPA_API_POD_BODY int spa_pod_is_array(const struct spa_pod *pod)
|
||||
{
|
||||
return SPA_POD_CHECK(pod, SPA_TYPE_Array, sizeof(struct spa_pod_array_body));
|
||||
}
|
||||
SPA_API_POD_BODY int spa_pod_body_get_array(const struct spa_pod *pod, const void *body,
|
||||
struct spa_pod_array *arr, const void **arr_body)
|
||||
{
|
||||
if (!spa_pod_is_array(pod))
|
||||
return -EINVAL;
|
||||
arr->pod = *pod;
|
||||
memcpy(&arr->body, body, sizeof(struct spa_pod_array_body));
|
||||
*arr_body = SPA_PTROFF(body, sizeof(struct spa_pod_array_body), void);
|
||||
return 0;
|
||||
}
|
||||
SPA_API_POD_BODY const void *spa_pod_array_body_get_values(const struct spa_pod_array *arr,
|
||||
const void *body, uint32_t *n_values, uint32_t *val_size, uint32_t *val_type)
|
||||
{
|
||||
uint32_t child_size = arr->body.child.size;
|
||||
*n_values = child_size ? (arr->pod.size - sizeof(arr->body)) / child_size : 0;
|
||||
*val_size = child_size;
|
||||
*val_type = arr->body.child.type;
|
||||
return body;
|
||||
}
|
||||
|
||||
SPA_API_POD_BODY const void *spa_pod_body_get_array_values(const struct spa_pod *pod,
|
||||
const void *body, uint32_t *n_values, uint32_t *val_size, uint32_t *val_type)
|
||||
{
|
||||
struct spa_pod_array arr;
|
||||
if (spa_pod_body_get_array(pod, body, &arr, &body) < 0)
|
||||
return NULL;
|
||||
return spa_pod_array_body_get_values(&arr, body, n_values, val_size, val_type);
|
||||
}
|
||||
|
||||
SPA_API_POD_BODY int spa_pod_is_choice(const struct spa_pod *pod)
|
||||
{
|
||||
return SPA_POD_CHECK(pod, SPA_TYPE_Choice, sizeof(struct spa_pod_choice_body));
|
||||
}
|
||||
SPA_API_POD_BODY int spa_pod_body_get_choice(const struct spa_pod *pod, const void *body,
|
||||
struct spa_pod_choice *choice, const void **choice_body)
|
||||
{
|
||||
if (!spa_pod_is_choice(pod))
|
||||
return -EINVAL;
|
||||
choice->pod = *pod;
|
||||
memcpy(&choice->body, body, sizeof(struct spa_pod_choice_body));
|
||||
if (choice->pod.size - sizeof(struct spa_pod_choice_body) < choice->body.child.size)
|
||||
return -EINVAL;
|
||||
*choice_body = SPA_PTROFF(body, sizeof(struct spa_pod_choice_body), void);
|
||||
return 0;
|
||||
}
|
||||
SPA_API_POD_BODY const void *spa_pod_choice_body_get_values(const struct spa_pod_choice *pod,
|
||||
const void *body, uint32_t *n_values, uint32_t *choice,
|
||||
uint32_t *val_size, uint32_t *val_type)
|
||||
{
|
||||
uint32_t child_size = pod->body.child.size;
|
||||
*val_size = child_size;
|
||||
*val_type = pod->body.child.type;
|
||||
*n_values = child_size ? (pod->pod.size - sizeof(pod->body)) / child_size : 0;
|
||||
*choice = pod->body.type;
|
||||
if (*choice == SPA_CHOICE_None)
|
||||
*n_values = SPA_MIN(1u, *n_values);
|
||||
return body;
|
||||
}
|
||||
|
||||
SPA_API_POD_BODY int spa_pod_is_struct(const struct spa_pod *pod)
|
||||
{
|
||||
return SPA_POD_CHECK_TYPE(pod, SPA_TYPE_Struct);
|
||||
}
|
||||
|
||||
SPA_API_POD_BODY int spa_pod_is_object(const struct spa_pod *pod)
|
||||
{
|
||||
return SPA_POD_CHECK(pod, SPA_TYPE_Object, sizeof(struct spa_pod_object_body));
|
||||
}
|
||||
SPA_API_POD_BODY int spa_pod_body_get_object(const struct spa_pod *pod, const void *body,
|
||||
struct spa_pod_object *object, const void **object_body)
|
||||
{
|
||||
if (!spa_pod_is_object(pod))
|
||||
return -EINVAL;
|
||||
object->pod = *pod;
|
||||
memcpy(&object->body, body, sizeof(struct spa_pod_object_body));
|
||||
*object_body = SPA_PTROFF(body, sizeof(struct spa_pod_object_body), void);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPA_API_POD_BODY int spa_pod_is_sequence(const struct spa_pod *pod)
|
||||
{
|
||||
return SPA_POD_CHECK(pod, SPA_TYPE_Sequence, sizeof(struct spa_pod_sequence_body));
|
||||
}
|
||||
SPA_API_POD_BODY int spa_pod_body_get_sequence(const struct spa_pod *pod, const void *body,
|
||||
struct spa_pod_sequence *seq, const void **seq_body)
|
||||
{
|
||||
if (!spa_pod_is_sequence(pod))
|
||||
return -EINVAL;
|
||||
seq->pod = *pod;
|
||||
memcpy(&seq->body, body, sizeof(struct spa_pod_sequence_body));
|
||||
*seq_body = SPA_PTROFF(body, sizeof(struct spa_pod_sequence_body), void);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* SPA_POD_BODY_H */
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
#include <stdarg.h>
|
||||
|
||||
#include <spa/utils/hook.h>
|
||||
#include <spa/pod/iter.h>
|
||||
#include <spa/pod/body.h>
|
||||
#include <spa/pod/vararg.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include <sys/types.h>
|
||||
|
||||
#include <spa/pod/pod.h>
|
||||
#include <spa/pod/body.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
|
@ -27,66 +28,6 @@ extern "C" {
|
|||
* \{
|
||||
*/
|
||||
|
||||
struct spa_pod_frame {
|
||||
struct spa_pod pod;
|
||||
struct spa_pod_frame *parent;
|
||||
uint32_t offset;
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
#define SPA_POD_IS_VALID(pod) \
|
||||
(SPA_POD_BODY_SIZE(pod) < SPA_POD_MAX_SIZE)
|
||||
|
||||
#define SPA_POD_CHECK_TYPE(pod,_type) \
|
||||
(SPA_POD_IS_VALID(pod) && \
|
||||
(pod)->type == (_type))
|
||||
|
||||
#define SPA_POD_CHECK(pod,_type,_size) \
|
||||
(SPA_POD_CHECK_TYPE(pod,_type) && (pod)->size >= (_size))
|
||||
|
||||
SPA_API_POD_ITER uint32_t spa_pod_type_size(uint32_t type)
|
||||
{
|
||||
switch (type) {
|
||||
case SPA_TYPE_None:
|
||||
case SPA_TYPE_Bytes:
|
||||
case SPA_TYPE_Struct:
|
||||
case SPA_TYPE_Pod:
|
||||
return 0;
|
||||
case SPA_TYPE_String:
|
||||
return 1;
|
||||
case SPA_TYPE_Bool:
|
||||
case SPA_TYPE_Int:
|
||||
return sizeof(int32_t);
|
||||
case SPA_TYPE_Id:
|
||||
return sizeof(uint32_t);
|
||||
case SPA_TYPE_Long:
|
||||
return sizeof(int64_t);
|
||||
case SPA_TYPE_Float:
|
||||
return sizeof(float);
|
||||
case SPA_TYPE_Double:
|
||||
return sizeof(double);
|
||||
case SPA_TYPE_Rectangle:
|
||||
return sizeof(struct spa_rectangle);
|
||||
case SPA_TYPE_Fraction:
|
||||
return sizeof(struct spa_fraction);
|
||||
case SPA_TYPE_Bitmap:
|
||||
return sizeof(uint8_t);
|
||||
case SPA_TYPE_Array:
|
||||
return sizeof(struct spa_pod_array_body);
|
||||
case SPA_TYPE_Object:
|
||||
return sizeof(struct spa_pod_object_body);
|
||||
case SPA_TYPE_Sequence:
|
||||
return sizeof(struct spa_pod_sequence_body);
|
||||
case SPA_TYPE_Pointer:
|
||||
return sizeof(struct spa_pod_pointer_body);
|
||||
case SPA_TYPE_Fd:
|
||||
return sizeof(int64_t);
|
||||
case SPA_TYPE_Choice:
|
||||
return sizeof(struct spa_pod_choice_body);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPA_API_POD_ITER bool spa_pod_is_inside(const void *pod, uint32_t size, const void *iter)
|
||||
{
|
||||
size_t remaining;
|
||||
|
|
@ -180,214 +121,82 @@ SPA_API_POD_ITER struct spa_pod_control *spa_pod_control_next(const struct spa_p
|
|||
|
||||
SPA_API_POD_ITER void *spa_pod_from_data(void *data, size_t maxsize, off_t offset, size_t size)
|
||||
{
|
||||
void *pod;
|
||||
if (offset < 0 || offset > (int64_t)UINT32_MAX)
|
||||
struct spa_pod pod;
|
||||
const void *body;
|
||||
if (spa_pod_body_from_data(data, maxsize, offset, size, &pod, &body) < 0)
|
||||
return NULL;
|
||||
if (size < sizeof(struct spa_pod) ||
|
||||
size > maxsize ||
|
||||
maxsize - size < (uint32_t)offset)
|
||||
return NULL;
|
||||
pod = SPA_PTROFF(data, offset, void);
|
||||
if (!SPA_POD_IS_VALID(pod))
|
||||
return NULL;
|
||||
if (SPA_POD_BODY_SIZE(pod) > size - sizeof(struct spa_pod))
|
||||
return NULL;
|
||||
return pod;
|
||||
}
|
||||
SPA_API_POD_ITER int spa_pod_is_none(const struct spa_pod *pod)
|
||||
{
|
||||
return SPA_POD_CHECK_TYPE(pod, SPA_TYPE_None);
|
||||
}
|
||||
|
||||
SPA_API_POD_ITER int spa_pod_is_bool(const struct spa_pod *pod)
|
||||
{
|
||||
return SPA_POD_CHECK(pod, SPA_TYPE_Bool, sizeof(int32_t));
|
||||
return SPA_PTROFF(data, offset, void);
|
||||
}
|
||||
|
||||
SPA_API_POD_ITER int spa_pod_get_bool(const struct spa_pod *pod, bool *value)
|
||||
{
|
||||
if (!spa_pod_is_bool(pod))
|
||||
return -EINVAL;
|
||||
*value = !!SPA_POD_VALUE(struct spa_pod_bool, pod);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPA_API_POD_ITER int spa_pod_is_id(const struct spa_pod *pod)
|
||||
{
|
||||
return SPA_POD_CHECK(pod, SPA_TYPE_Id, sizeof(uint32_t));
|
||||
return spa_pod_body_get_bool(pod, SPA_POD_BODY_CONST(pod), value);
|
||||
}
|
||||
|
||||
SPA_API_POD_ITER int spa_pod_get_id(const struct spa_pod *pod, uint32_t *value)
|
||||
{
|
||||
if (!spa_pod_is_id(pod))
|
||||
return -EINVAL;
|
||||
*value = SPA_POD_VALUE(struct spa_pod_id, pod);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPA_API_POD_ITER int spa_pod_is_int(const struct spa_pod *pod)
|
||||
{
|
||||
return SPA_POD_CHECK(pod, SPA_TYPE_Int, sizeof(int32_t));
|
||||
return spa_pod_body_get_id(pod, SPA_POD_BODY_CONST(pod), value);
|
||||
}
|
||||
|
||||
SPA_API_POD_ITER int spa_pod_get_int(const struct spa_pod *pod, int32_t *value)
|
||||
{
|
||||
if (!spa_pod_is_int(pod))
|
||||
return -EINVAL;
|
||||
*value = SPA_POD_VALUE(struct spa_pod_int, pod);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPA_API_POD_ITER int spa_pod_is_long(const struct spa_pod *pod)
|
||||
{
|
||||
return SPA_POD_CHECK(pod, SPA_TYPE_Long, sizeof(int64_t));
|
||||
return spa_pod_body_get_int(pod, SPA_POD_BODY_CONST(pod), value);
|
||||
}
|
||||
|
||||
SPA_API_POD_ITER int spa_pod_get_long(const struct spa_pod *pod, int64_t *value)
|
||||
{
|
||||
if (!spa_pod_is_long(pod))
|
||||
return -EINVAL;
|
||||
*value = SPA_POD_VALUE(struct spa_pod_long, pod);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPA_API_POD_ITER int spa_pod_is_float(const struct spa_pod *pod)
|
||||
{
|
||||
return SPA_POD_CHECK(pod, SPA_TYPE_Float, sizeof(float));
|
||||
return spa_pod_body_get_long(pod, SPA_POD_BODY_CONST(pod), value);
|
||||
}
|
||||
|
||||
SPA_API_POD_ITER int spa_pod_get_float(const struct spa_pod *pod, float *value)
|
||||
{
|
||||
if (!spa_pod_is_float(pod))
|
||||
return -EINVAL;
|
||||
*value = SPA_POD_VALUE(struct spa_pod_float, pod);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPA_API_POD_ITER int spa_pod_is_double(const struct spa_pod *pod)
|
||||
{
|
||||
return SPA_POD_CHECK(pod, SPA_TYPE_Double, sizeof(double));
|
||||
return spa_pod_body_get_float(pod, SPA_POD_BODY_CONST(pod), value);
|
||||
}
|
||||
|
||||
SPA_API_POD_ITER int spa_pod_get_double(const struct spa_pod *pod, double *value)
|
||||
{
|
||||
if (!spa_pod_is_double(pod))
|
||||
return -EINVAL;
|
||||
*value = SPA_POD_VALUE(struct spa_pod_double, pod);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPA_API_POD_ITER int spa_pod_is_string(const struct spa_pod *pod)
|
||||
{
|
||||
return SPA_POD_CHECK(pod, SPA_TYPE_String, 1);
|
||||
return spa_pod_body_get_double(pod, SPA_POD_BODY_CONST(pod), value);
|
||||
}
|
||||
|
||||
SPA_API_POD_ITER int spa_pod_get_string(const struct spa_pod *pod, const char **value)
|
||||
{
|
||||
const char *s;
|
||||
if (!spa_pod_is_string(pod))
|
||||
return -EINVAL;
|
||||
s = (const char *)SPA_POD_CONTENTS(struct spa_pod_string, pod);
|
||||
if (s[pod->size-1] != '\0')
|
||||
return -EINVAL;
|
||||
*value = s;
|
||||
return 0;
|
||||
return spa_pod_body_get_string(pod, SPA_POD_BODY_CONST(pod), value);
|
||||
}
|
||||
|
||||
SPA_API_POD_ITER int spa_pod_copy_string(const struct spa_pod *pod, size_t maxlen, char *dest)
|
||||
{
|
||||
const char *s;
|
||||
if (spa_pod_get_string(pod, &s) < 0 || maxlen < 1)
|
||||
return -EINVAL;
|
||||
strncpy(dest, s, maxlen-1);
|
||||
dest[maxlen-1]= '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPA_API_POD_ITER int spa_pod_is_bytes(const struct spa_pod *pod)
|
||||
{
|
||||
return SPA_POD_CHECK_TYPE(pod, SPA_TYPE_Bytes);
|
||||
return spa_pod_body_copy_string(pod, SPA_POD_BODY_CONST(pod), maxlen, dest);
|
||||
}
|
||||
|
||||
SPA_API_POD_ITER int spa_pod_get_bytes(const struct spa_pod *pod, const void **value, uint32_t *len)
|
||||
{
|
||||
if (!spa_pod_is_bytes(pod))
|
||||
return -EINVAL;
|
||||
*value = (const void *)SPA_POD_CONTENTS(struct spa_pod_bytes, pod);
|
||||
*len = pod->size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPA_API_POD_ITER int spa_pod_is_pointer(const struct spa_pod *pod)
|
||||
{
|
||||
return SPA_POD_CHECK(pod, SPA_TYPE_Pointer, sizeof(struct spa_pod_pointer_body));
|
||||
return spa_pod_body_get_bytes(pod, SPA_POD_BODY_CONST(pod), value, len);
|
||||
}
|
||||
|
||||
SPA_API_POD_ITER int spa_pod_get_pointer(const struct spa_pod *pod, uint32_t *type, const void **value)
|
||||
{
|
||||
if (!spa_pod_is_pointer(pod))
|
||||
return -EINVAL;
|
||||
*type = ((struct spa_pod_pointer*)pod)->body.type;
|
||||
*value = ((struct spa_pod_pointer*)pod)->body.value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPA_API_POD_ITER int spa_pod_is_fd(const struct spa_pod *pod)
|
||||
{
|
||||
return SPA_POD_CHECK(pod, SPA_TYPE_Fd, sizeof(int64_t));
|
||||
return spa_pod_body_get_pointer(pod, SPA_POD_BODY_CONST(pod), type, value);
|
||||
}
|
||||
|
||||
SPA_API_POD_ITER int spa_pod_get_fd(const struct spa_pod *pod, int64_t *value)
|
||||
{
|
||||
if (!spa_pod_is_fd(pod))
|
||||
return -EINVAL;
|
||||
*value = SPA_POD_VALUE(struct spa_pod_fd, pod);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPA_API_POD_ITER int spa_pod_is_rectangle(const struct spa_pod *pod)
|
||||
{
|
||||
return SPA_POD_CHECK(pod, SPA_TYPE_Rectangle, sizeof(struct spa_rectangle));
|
||||
return spa_pod_body_get_fd(pod, SPA_POD_BODY_CONST(pod), value);
|
||||
}
|
||||
|
||||
SPA_API_POD_ITER int spa_pod_get_rectangle(const struct spa_pod *pod, struct spa_rectangle *value)
|
||||
{
|
||||
if (!spa_pod_is_rectangle(pod))
|
||||
return -EINVAL;
|
||||
*value = SPA_POD_VALUE(struct spa_pod_rectangle, pod);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPA_API_POD_ITER int spa_pod_is_fraction(const struct spa_pod *pod)
|
||||
{
|
||||
return SPA_POD_CHECK(pod, SPA_TYPE_Fraction, sizeof(struct spa_fraction));
|
||||
return spa_pod_body_get_rectangle(pod, SPA_POD_BODY_CONST(pod), value);
|
||||
}
|
||||
|
||||
SPA_API_POD_ITER int spa_pod_get_fraction(const struct spa_pod *pod, struct spa_fraction *value)
|
||||
{
|
||||
spa_return_val_if_fail(spa_pod_is_fraction(pod), -EINVAL);
|
||||
*value = SPA_POD_VALUE(struct spa_pod_fraction, pod);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPA_API_POD_ITER int spa_pod_is_bitmap(const struct spa_pod *pod)
|
||||
{
|
||||
return SPA_POD_CHECK(pod, SPA_TYPE_Bitmap, sizeof(uint8_t));
|
||||
}
|
||||
|
||||
SPA_API_POD_ITER int spa_pod_is_array(const struct spa_pod *pod)
|
||||
{
|
||||
return SPA_POD_CHECK(pod, SPA_TYPE_Array, sizeof(struct spa_pod_array_body));
|
||||
return spa_pod_body_get_fraction(pod, SPA_POD_BODY_CONST(pod), value);
|
||||
}
|
||||
|
||||
SPA_API_POD_ITER void *spa_pod_get_array_full(const struct spa_pod *pod, uint32_t *n_values,
|
||||
uint32_t *val_size, uint32_t *val_type)
|
||||
{
|
||||
spa_return_val_if_fail(spa_pod_is_array(pod), NULL);
|
||||
*n_values = SPA_POD_ARRAY_N_VALUES(pod);
|
||||
*val_size = SPA_POD_ARRAY_VALUE_SIZE(pod);
|
||||
*val_type = SPA_POD_ARRAY_VALUE_TYPE(pod);
|
||||
return SPA_POD_ARRAY_VALUES(pod);
|
||||
return (void*)spa_pod_body_get_array_values(pod, SPA_POD_BODY(pod), n_values, val_size, val_type);
|
||||
}
|
||||
SPA_API_POD_ITER void *spa_pod_get_array(const struct spa_pod *pod, uint32_t *n_values)
|
||||
{
|
||||
|
|
@ -399,7 +208,7 @@ SPA_API_POD_ITER uint32_t spa_pod_copy_array_full(const struct spa_pod *pod, uin
|
|||
uint32_t size, void *values, uint32_t max_values)
|
||||
{
|
||||
uint32_t n_values, val_size, val_type;
|
||||
void *v = spa_pod_get_array_full(pod, &n_values, &val_size, &val_type);
|
||||
const void *v = spa_pod_get_array_full(pod, &n_values, &val_size, &val_type);
|
||||
if (v == NULL || max_values == 0 || val_type != type || val_size != size)
|
||||
return 0;
|
||||
n_values = SPA_MIN(n_values, max_values);
|
||||
|
|
@ -410,20 +219,20 @@ SPA_API_POD_ITER uint32_t spa_pod_copy_array_full(const struct spa_pod *pod, uin
|
|||
#define spa_pod_copy_array(pod,type,values,max_values) \
|
||||
spa_pod_copy_array_full(pod,type,sizeof(values[0]),values,max_values)
|
||||
|
||||
SPA_API_POD_ITER int spa_pod_is_choice(const struct spa_pod *pod)
|
||||
{
|
||||
return SPA_POD_CHECK(pod, SPA_TYPE_Choice, sizeof(struct spa_pod_choice_body));
|
||||
}
|
||||
|
||||
SPA_API_POD_ITER struct spa_pod *spa_pod_get_values(const struct spa_pod *pod,
|
||||
uint32_t *n_vals, uint32_t *choice)
|
||||
{
|
||||
if (spa_pod_is_choice(pod)) {
|
||||
*n_vals = SPA_POD_CHOICE_N_VALUES(pod);
|
||||
*choice = SPA_POD_CHOICE_TYPE(pod);
|
||||
if (*choice == SPA_CHOICE_None)
|
||||
*n_vals = SPA_MIN(1u, *n_vals);
|
||||
return (struct spa_pod*)SPA_POD_CHOICE_CHILD(pod);
|
||||
const struct spa_pod_choice *p = (const struct spa_pod_choice*)pod;
|
||||
uint32_t type, size;
|
||||
spa_pod_choice_body_get_values(p, SPA_POD_BODY_CONST(p), n_vals, choice, &size, &type);
|
||||
return (struct spa_pod*)&p->body.child;
|
||||
} else if (spa_pod_is_array(pod)) {
|
||||
const struct spa_pod_array *p = (const struct spa_pod_array*)pod;
|
||||
uint32_t type, size;
|
||||
spa_pod_array_body_get_values(p, SPA_POD_BODY_CONST(p), n_vals, &size, &type);
|
||||
*choice = SPA_CHOICE_None;
|
||||
return (struct spa_pod*)&p->body.child;
|
||||
} else {
|
||||
*n_vals = 1;
|
||||
*choice = SPA_CHOICE_None;
|
||||
|
|
@ -431,16 +240,6 @@ SPA_API_POD_ITER struct spa_pod *spa_pod_get_values(const struct spa_pod *pod,
|
|||
}
|
||||
}
|
||||
|
||||
SPA_API_POD_ITER int spa_pod_is_struct(const struct spa_pod *pod)
|
||||
{
|
||||
return SPA_POD_CHECK_TYPE(pod, SPA_TYPE_Struct);
|
||||
}
|
||||
|
||||
SPA_API_POD_ITER int spa_pod_is_object(const struct spa_pod *pod)
|
||||
{
|
||||
return SPA_POD_CHECK(pod, SPA_TYPE_Object, sizeof(struct spa_pod_object_body));
|
||||
}
|
||||
|
||||
SPA_API_POD_ITER bool spa_pod_is_object_type(const struct spa_pod *pod, uint32_t type)
|
||||
{
|
||||
return (pod && spa_pod_is_object(pod) && SPA_POD_OBJECT_TYPE(pod) == type);
|
||||
|
|
@ -451,11 +250,6 @@ SPA_API_POD_ITER bool spa_pod_is_object_id(const struct spa_pod *pod, uint32_t i
|
|||
return (pod && spa_pod_is_object(pod) && SPA_POD_OBJECT_ID(pod) == id);
|
||||
}
|
||||
|
||||
SPA_API_POD_ITER int spa_pod_is_sequence(const struct spa_pod *pod)
|
||||
{
|
||||
return SPA_POD_CHECK(pod, SPA_TYPE_Sequence, sizeof(struct spa_pod_sequence_body));
|
||||
}
|
||||
|
||||
SPA_API_POD_ITER const struct spa_pod_prop *spa_pod_object_find_prop(const struct spa_pod_object *pod,
|
||||
const struct spa_pod_prop *start, uint32_t key)
|
||||
{
|
||||
|
|
@ -535,4 +329,4 @@ SPA_API_POD_ITER int spa_pod_is_fixated(const struct spa_pod *pod)
|
|||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* SPA_POD_H */
|
||||
#endif /* SPA_POD_ITER_H */
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <spa/pod/iter.h>
|
||||
#include <spa/pod/body.h>
|
||||
#include <spa/pod/vararg.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
@ -55,6 +55,22 @@ SPA_API_POD_PARSER void spa_pod_parser_pod(struct spa_pod_parser *parser,
|
|||
spa_pod_parser_init(parser, pod, SPA_POD_SIZE(pod));
|
||||
}
|
||||
|
||||
SPA_API_POD_PARSER void spa_pod_parser_init_pod_body(struct spa_pod_parser *parser,
|
||||
const struct spa_pod *pod, const void *body)
|
||||
{
|
||||
spa_pod_parser_init(parser,
|
||||
SPA_PTROFF(body, -sizeof(struct spa_pod), const struct spa_pod),
|
||||
pod->size + sizeof(struct spa_pod));
|
||||
}
|
||||
SPA_API_POD_PARSER void spa_pod_parser_init_from_data(struct spa_pod_parser *parser,
|
||||
const void *data, uint32_t maxsize, uint32_t offset, uint32_t size)
|
||||
{
|
||||
size_t offs, sz;
|
||||
offs = SPA_MIN(offset, maxsize);
|
||||
sz = SPA_MIN(maxsize - offs, size);
|
||||
spa_pod_parser_init(parser, SPA_PTROFF(data, offs, void), sz);
|
||||
}
|
||||
|
||||
SPA_API_POD_PARSER void
|
||||
spa_pod_parser_get_state(struct spa_pod_parser *parser, struct spa_pod_parser_state *state)
|
||||
{
|
||||
|
|
@ -67,21 +83,32 @@ spa_pod_parser_reset(struct spa_pod_parser *parser, struct spa_pod_parser_state
|
|||
parser->state = *state;
|
||||
}
|
||||
|
||||
SPA_API_POD_PARSER int
|
||||
spa_pod_parser_read_header(struct spa_pod_parser *parser, uint32_t offset, uint32_t size,
|
||||
void *header, uint32_t header_size, uint32_t pod_offset, const void **body)
|
||||
{
|
||||
/* Cast to uint64_t to avoid wraparound. */
|
||||
const uint64_t long_offset = (uint64_t)offset + header_size;
|
||||
if (long_offset <= size && (offset & 7) == 0) {
|
||||
memcpy(header, SPA_PTROFF(parser->data, offset, void), header_size);
|
||||
struct spa_pod *pod = SPA_PTROFF(header, pod_offset, struct spa_pod);
|
||||
/* Check that the size (rounded to the next multiple of 8) is in bounds. */
|
||||
if (long_offset + SPA_ROUND_UP_N((uint64_t)pod->size, SPA_POD_ALIGN) <= size) {
|
||||
*body = SPA_PTROFF(parser->data, long_offset, void);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -EPIPE;
|
||||
}
|
||||
|
||||
SPA_API_POD_PARSER struct spa_pod *
|
||||
spa_pod_parser_deref(struct spa_pod_parser *parser, uint32_t offset, uint32_t size)
|
||||
{
|
||||
/* Cast to uint64_t to avoid wraparound. Add 8 for the pod itself. */
|
||||
const uint64_t long_offset = (uint64_t)offset + 8;
|
||||
if (long_offset <= size && (offset & 7) == 0) {
|
||||
/* Use void* because creating a misaligned pointer is undefined. */
|
||||
void *pod = SPA_PTROFF(parser->data, offset, void);
|
||||
/*
|
||||
* Check that the size (rounded to the next multiple of 8) is in bounds.
|
||||
*/
|
||||
if (long_offset + SPA_ROUND_UP_N((uint64_t)SPA_POD_BODY_SIZE(pod), SPA_POD_ALIGN) <= size)
|
||||
return (struct spa_pod *)pod;
|
||||
}
|
||||
return NULL;
|
||||
struct spa_pod pod;
|
||||
const void *body;
|
||||
if (spa_pod_parser_read_header(parser, offset, size, &pod, sizeof(pod), 0, &body) < 0)
|
||||
return NULL;
|
||||
return SPA_PTROFF(body, -sizeof(pod), struct spa_pod);
|
||||
}
|
||||
|
||||
SPA_API_POD_PARSER struct spa_pod *spa_pod_parser_frame(struct spa_pod_parser *parser, struct spa_pod_frame *frame)
|
||||
|
|
@ -99,11 +126,28 @@ SPA_API_POD_PARSER void spa_pod_parser_push(struct spa_pod_parser *parser,
|
|||
parser->state.frame = frame;
|
||||
}
|
||||
|
||||
SPA_API_POD_PARSER struct spa_pod *spa_pod_parser_current(struct spa_pod_parser *parser)
|
||||
SPA_API_POD_PARSER int spa_pod_parser_get_header(struct spa_pod_parser *parser,
|
||||
void *header, uint32_t header_size, uint32_t pod_offset, const void **body)
|
||||
{
|
||||
struct spa_pod_frame *f = parser->state.frame;
|
||||
uint32_t size = f ? f->offset + SPA_POD_SIZE(&f->pod) : parser->size;
|
||||
return spa_pod_parser_deref(parser, parser->state.offset, size);
|
||||
return spa_pod_parser_read_header(parser, parser->state.offset, size,
|
||||
header, header_size, pod_offset, body);
|
||||
}
|
||||
|
||||
SPA_API_POD_PARSER int spa_pod_parser_current_body(struct spa_pod_parser *parser,
|
||||
struct spa_pod *pod, const void **body)
|
||||
{
|
||||
return spa_pod_parser_get_header(parser, pod, sizeof(struct spa_pod), 0, body);
|
||||
}
|
||||
|
||||
SPA_API_POD_PARSER struct spa_pod *spa_pod_parser_current(struct spa_pod_parser *parser)
|
||||
{
|
||||
struct spa_pod pod;
|
||||
const void *body;
|
||||
if (spa_pod_parser_current_body(parser, &pod, &body) < 0)
|
||||
return NULL;
|
||||
return SPA_PTROFF(body, -sizeof(struct spa_pod), struct spa_pod);
|
||||
}
|
||||
|
||||
SPA_API_POD_PARSER void spa_pod_parser_advance(struct spa_pod_parser *parser, const struct spa_pod *pod)
|
||||
|
|
@ -111,171 +155,351 @@ SPA_API_POD_PARSER void spa_pod_parser_advance(struct spa_pod_parser *parser, co
|
|||
parser->state.offset += SPA_ROUND_UP_N(SPA_POD_SIZE(pod), SPA_POD_ALIGN);
|
||||
}
|
||||
|
||||
SPA_API_POD_PARSER struct spa_pod *spa_pod_parser_next(struct spa_pod_parser *parser)
|
||||
SPA_API_POD_PARSER int spa_pod_parser_next_body(struct spa_pod_parser *parser,
|
||||
struct spa_pod *pod, const void **body)
|
||||
{
|
||||
struct spa_pod *pod = spa_pod_parser_current(parser);
|
||||
if (pod)
|
||||
spa_pod_parser_advance(parser, pod);
|
||||
return pod;
|
||||
if (spa_pod_parser_current_body(parser, pod, body) < 0)
|
||||
return -EINVAL;
|
||||
spa_pod_parser_advance(parser, pod);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPA_API_POD_PARSER int spa_pod_parser_pop(struct spa_pod_parser *parser,
|
||||
SPA_API_POD_PARSER struct spa_pod *spa_pod_parser_next(struct spa_pod_parser *parser)
|
||||
{
|
||||
struct spa_pod pod;
|
||||
const void *body;
|
||||
if (spa_pod_parser_current_body(parser, &pod, &body) < 0)
|
||||
return NULL;
|
||||
spa_pod_parser_advance(parser, &pod);
|
||||
return SPA_PTROFF(body, -sizeof(struct spa_pod), struct spa_pod);
|
||||
}
|
||||
|
||||
SPA_API_POD_PARSER void spa_pod_parser_restart(struct spa_pod_parser *parser,
|
||||
struct spa_pod_frame *frame)
|
||||
{
|
||||
parser->state.offset = frame->offset;
|
||||
}
|
||||
|
||||
SPA_API_POD_PARSER void spa_pod_parser_unpush(struct spa_pod_parser *parser,
|
||||
struct spa_pod_frame *frame)
|
||||
{
|
||||
spa_pod_parser_restart(parser, frame);
|
||||
parser->state.frame = frame->parent;
|
||||
parser->state.offset = frame->offset + SPA_ROUND_UP_N(SPA_POD_SIZE(&frame->pod), SPA_POD_ALIGN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPA_API_POD_PARSER void spa_pod_parser_pop(struct spa_pod_parser *parser,
|
||||
struct spa_pod_frame *frame)
|
||||
{
|
||||
spa_pod_parser_unpush(parser, frame);
|
||||
spa_pod_parser_advance(parser, &frame->pod);
|
||||
}
|
||||
|
||||
SPA_API_POD_PARSER int spa_pod_parser_get_bool(struct spa_pod_parser *parser, bool *value)
|
||||
{
|
||||
int res = -EPIPE;
|
||||
const struct spa_pod *pod = spa_pod_parser_current(parser);
|
||||
if (pod != NULL && (res = spa_pod_get_bool(pod, value)) >= 0)
|
||||
spa_pod_parser_advance(parser, pod);
|
||||
int res;
|
||||
struct spa_pod pod;
|
||||
const void *body;
|
||||
if ((res = spa_pod_parser_current_body(parser, &pod, &body)) < 0)
|
||||
return res;
|
||||
if ((res = spa_pod_body_get_bool(&pod, body, value)) >= 0)
|
||||
spa_pod_parser_advance(parser, &pod);
|
||||
return res;
|
||||
}
|
||||
|
||||
SPA_API_POD_PARSER int spa_pod_parser_get_id(struct spa_pod_parser *parser, uint32_t *value)
|
||||
{
|
||||
int res = -EPIPE;
|
||||
const struct spa_pod *pod = spa_pod_parser_current(parser);
|
||||
if (pod != NULL && (res = spa_pod_get_id(pod, value)) >= 0)
|
||||
spa_pod_parser_advance(parser, pod);
|
||||
int res;
|
||||
struct spa_pod pod;
|
||||
const void *body;
|
||||
if ((res = spa_pod_parser_current_body(parser, &pod, &body)) < 0)
|
||||
return res;
|
||||
if ((res = spa_pod_body_get_id(&pod, body, value)) >= 0)
|
||||
spa_pod_parser_advance(parser, &pod);
|
||||
return res;
|
||||
}
|
||||
|
||||
SPA_API_POD_PARSER int spa_pod_parser_get_int(struct spa_pod_parser *parser, int32_t *value)
|
||||
{
|
||||
int res = -EPIPE;
|
||||
const struct spa_pod *pod = spa_pod_parser_current(parser);
|
||||
if (pod != NULL && (res = spa_pod_get_int(pod, value)) >= 0)
|
||||
spa_pod_parser_advance(parser, pod);
|
||||
int res;
|
||||
struct spa_pod pod;
|
||||
const void *body;
|
||||
if ((res = spa_pod_parser_current_body(parser, &pod, &body)) < 0)
|
||||
return res;
|
||||
if ((res = spa_pod_body_get_int(&pod, body, value)) >= 0)
|
||||
spa_pod_parser_advance(parser, &pod);
|
||||
return res;
|
||||
}
|
||||
|
||||
SPA_API_POD_PARSER int spa_pod_parser_get_long(struct spa_pod_parser *parser, int64_t *value)
|
||||
{
|
||||
int res = -EPIPE;
|
||||
const struct spa_pod *pod = spa_pod_parser_current(parser);
|
||||
if (pod != NULL && (res = spa_pod_get_long(pod, value)) >= 0)
|
||||
spa_pod_parser_advance(parser, pod);
|
||||
int res;
|
||||
struct spa_pod pod;
|
||||
const void *body;
|
||||
if ((res = spa_pod_parser_current_body(parser, &pod, &body)) < 0)
|
||||
return res;
|
||||
if ((res = spa_pod_body_get_long(&pod, body, value)) >= 0)
|
||||
spa_pod_parser_advance(parser, &pod);
|
||||
return res;
|
||||
}
|
||||
|
||||
SPA_API_POD_PARSER int spa_pod_parser_get_float(struct spa_pod_parser *parser, float *value)
|
||||
{
|
||||
int res = -EPIPE;
|
||||
const struct spa_pod *pod = spa_pod_parser_current(parser);
|
||||
if (pod != NULL && (res = spa_pod_get_float(pod, value)) >= 0)
|
||||
spa_pod_parser_advance(parser, pod);
|
||||
int res;
|
||||
struct spa_pod pod;
|
||||
const void *body;
|
||||
if ((res = spa_pod_parser_current_body(parser, &pod, &body)) < 0)
|
||||
return res;
|
||||
if ((res = spa_pod_body_get_float(&pod, body, value)) >= 0)
|
||||
spa_pod_parser_advance(parser, &pod);
|
||||
return res;
|
||||
}
|
||||
|
||||
SPA_API_POD_PARSER int spa_pod_parser_get_double(struct spa_pod_parser *parser, double *value)
|
||||
{
|
||||
int res = -EPIPE;
|
||||
const struct spa_pod *pod = spa_pod_parser_current(parser);
|
||||
if (pod != NULL && (res = spa_pod_get_double(pod, value)) >= 0)
|
||||
spa_pod_parser_advance(parser, pod);
|
||||
int res;
|
||||
struct spa_pod pod;
|
||||
const void *body;
|
||||
if ((res = spa_pod_parser_current_body(parser, &pod, &body)) < 0)
|
||||
return res;
|
||||
if ((res = spa_pod_body_get_double(&pod, body, value)) >= 0)
|
||||
spa_pod_parser_advance(parser, &pod);
|
||||
return res;
|
||||
}
|
||||
|
||||
SPA_API_POD_PARSER int spa_pod_parser_get_string(struct spa_pod_parser *parser, const char **value)
|
||||
{
|
||||
int res = -EPIPE;
|
||||
const struct spa_pod *pod = spa_pod_parser_current(parser);
|
||||
if (pod != NULL && (res = spa_pod_get_string(pod, value)) >= 0)
|
||||
spa_pod_parser_advance(parser, pod);
|
||||
int res;
|
||||
struct spa_pod pod;
|
||||
const void *body;
|
||||
if ((res = spa_pod_parser_current_body(parser, &pod, &body)) < 0)
|
||||
return res;
|
||||
if ((res = spa_pod_body_get_string(&pod, body, value)) >= 0)
|
||||
spa_pod_parser_advance(parser, &pod);
|
||||
return res;
|
||||
}
|
||||
|
||||
SPA_API_POD_PARSER int spa_pod_parser_get_bytes(struct spa_pod_parser *parser, const void **value, uint32_t *len)
|
||||
{
|
||||
int res = -EPIPE;
|
||||
const struct spa_pod *pod = spa_pod_parser_current(parser);
|
||||
if (pod != NULL && (res = spa_pod_get_bytes(pod, value, len)) >= 0)
|
||||
spa_pod_parser_advance(parser, pod);
|
||||
int res;
|
||||
struct spa_pod pod;
|
||||
const void *body;
|
||||
if ((res = spa_pod_parser_current_body(parser, &pod, &body)) < 0)
|
||||
return res;
|
||||
if ((res = spa_pod_body_get_bytes(&pod, body, value, len)) >= 0)
|
||||
spa_pod_parser_advance(parser, &pod);
|
||||
return res;
|
||||
}
|
||||
|
||||
SPA_API_POD_PARSER int spa_pod_parser_get_pointer(struct spa_pod_parser *parser, uint32_t *type, const void **value)
|
||||
{
|
||||
int res = -EPIPE;
|
||||
const struct spa_pod *pod = spa_pod_parser_current(parser);
|
||||
if (pod != NULL && (res = spa_pod_get_pointer(pod, type, value)) >= 0)
|
||||
spa_pod_parser_advance(parser, pod);
|
||||
int res;
|
||||
struct spa_pod pod;
|
||||
const void *body;
|
||||
if ((res = spa_pod_parser_current_body(parser, &pod, &body)) < 0)
|
||||
return res;
|
||||
if ((res = spa_pod_body_get_pointer(&pod, body, type, value)) >= 0)
|
||||
spa_pod_parser_advance(parser, &pod);
|
||||
return res;
|
||||
}
|
||||
|
||||
SPA_API_POD_PARSER int spa_pod_parser_get_fd(struct spa_pod_parser *parser, int64_t *value)
|
||||
{
|
||||
int res = -EPIPE;
|
||||
const struct spa_pod *pod = spa_pod_parser_current(parser);
|
||||
if (pod != NULL && (res = spa_pod_get_fd(pod, value)) >= 0)
|
||||
spa_pod_parser_advance(parser, pod);
|
||||
int res;
|
||||
struct spa_pod pod;
|
||||
const void *body;
|
||||
if ((res = spa_pod_parser_current_body(parser, &pod, &body)) < 0)
|
||||
return res;
|
||||
if ((res = spa_pod_body_get_fd(&pod, body, value)) >= 0)
|
||||
spa_pod_parser_advance(parser, &pod);
|
||||
return res;
|
||||
}
|
||||
|
||||
SPA_API_POD_PARSER int spa_pod_parser_get_rectangle(struct spa_pod_parser *parser, struct spa_rectangle *value)
|
||||
{
|
||||
int res = -EPIPE;
|
||||
const struct spa_pod *pod = spa_pod_parser_current(parser);
|
||||
if (pod != NULL && (res = spa_pod_get_rectangle(pod, value)) >= 0)
|
||||
spa_pod_parser_advance(parser, pod);
|
||||
int res;
|
||||
struct spa_pod pod;
|
||||
const void *body;
|
||||
if ((res = spa_pod_parser_current_body(parser, &pod, &body)) < 0)
|
||||
return res;
|
||||
if ((res = spa_pod_body_get_rectangle(&pod, body, value)) >= 0)
|
||||
spa_pod_parser_advance(parser, &pod);
|
||||
return res;
|
||||
}
|
||||
|
||||
SPA_API_POD_PARSER int spa_pod_parser_get_fraction(struct spa_pod_parser *parser, struct spa_fraction *value)
|
||||
{
|
||||
int res = -EPIPE;
|
||||
const struct spa_pod *pod = spa_pod_parser_current(parser);
|
||||
if (pod != NULL && (res = spa_pod_get_fraction(pod, value)) >= 0)
|
||||
spa_pod_parser_advance(parser, pod);
|
||||
int res;
|
||||
struct spa_pod pod;
|
||||
const void *body;
|
||||
if ((res = spa_pod_parser_current_body(parser, &pod, &body)) < 0)
|
||||
return res;
|
||||
if ((res = spa_pod_body_get_fraction(&pod, body, value)) >= 0)
|
||||
spa_pod_parser_advance(parser, &pod);
|
||||
return res;
|
||||
}
|
||||
|
||||
SPA_API_POD_PARSER int spa_pod_parser_get_pod_body(struct spa_pod_parser *parser,
|
||||
struct spa_pod *value, const void **body)
|
||||
{
|
||||
int res;
|
||||
if ((res = spa_pod_parser_current_body(parser, value, body)) < 0)
|
||||
return res;
|
||||
spa_pod_parser_advance(parser, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPA_API_POD_PARSER int spa_pod_parser_get_pod(struct spa_pod_parser *parser, struct spa_pod **value)
|
||||
{
|
||||
struct spa_pod *pod = spa_pod_parser_current(parser);
|
||||
if (pod == NULL)
|
||||
return -EPIPE;
|
||||
*value = pod;
|
||||
spa_pod_parser_advance(parser, pod);
|
||||
int res;
|
||||
struct spa_pod pod;
|
||||
const void *body;
|
||||
if ((res = spa_pod_parser_get_pod_body(parser, &pod, &body)) < 0)
|
||||
return res;
|
||||
*value = SPA_PTROFF(body, -sizeof(struct spa_pod), struct spa_pod);
|
||||
return 0;
|
||||
}
|
||||
SPA_API_POD_PARSER int spa_pod_parser_push_struct(struct spa_pod_parser *parser,
|
||||
struct spa_pod_frame *frame)
|
||||
|
||||
SPA_API_POD_PARSER int spa_pod_parser_init_struct_body(struct spa_pod_parser *parser,
|
||||
struct spa_pod_frame *frame, const struct spa_pod *pod, const void *body)
|
||||
{
|
||||
const struct spa_pod *pod = spa_pod_parser_current(parser);
|
||||
if (pod == NULL)
|
||||
return -EPIPE;
|
||||
if (!spa_pod_is_struct(pod))
|
||||
return -EINVAL;
|
||||
spa_pod_parser_init_pod_body(parser, pod, body);
|
||||
spa_pod_parser_push(parser, frame, pod, parser->state.offset);
|
||||
parser->state.offset += sizeof(struct spa_pod_struct);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPA_API_POD_PARSER int spa_pod_parser_push_object(struct spa_pod_parser *parser,
|
||||
struct spa_pod_frame *frame, uint32_t type, uint32_t *id)
|
||||
SPA_API_POD_PARSER int spa_pod_parser_push_struct_body(struct spa_pod_parser *parser,
|
||||
struct spa_pod_frame *frame, struct spa_pod *str, const void **str_body)
|
||||
{
|
||||
const struct spa_pod *pod = spa_pod_parser_current(parser);
|
||||
if (pod == NULL)
|
||||
return -EPIPE;
|
||||
int res;
|
||||
if ((res = spa_pod_parser_current_body(parser, str, str_body)) < 0)
|
||||
return res;
|
||||
if (!spa_pod_is_struct(str))
|
||||
return -EINVAL;
|
||||
spa_pod_parser_push(parser, frame, str, parser->state.offset);
|
||||
parser->state.offset += sizeof(struct spa_pod_struct);
|
||||
return 0;
|
||||
}
|
||||
SPA_API_POD_PARSER int spa_pod_parser_push_struct(struct spa_pod_parser *parser,
|
||||
struct spa_pod_frame *frame)
|
||||
{
|
||||
struct spa_pod pod;
|
||||
const void *body;
|
||||
return spa_pod_parser_push_struct_body(parser, frame, &pod, &body);
|
||||
}
|
||||
|
||||
SPA_API_POD_PARSER int spa_pod_parser_init_object_body(struct spa_pod_parser *parser,
|
||||
struct spa_pod_frame *frame, const struct spa_pod *pod, const void *body,
|
||||
struct spa_pod_object *object, const void **object_body)
|
||||
{
|
||||
int res;
|
||||
if (!spa_pod_is_object(pod))
|
||||
return -EINVAL;
|
||||
if (type != SPA_POD_OBJECT_TYPE(pod))
|
||||
return -EPROTO;
|
||||
if (id != NULL)
|
||||
*id = SPA_POD_OBJECT_ID(pod);
|
||||
spa_pod_parser_init_pod_body(parser, pod, body);
|
||||
if ((res = spa_pod_body_get_object(pod, body, object, object_body)) < 0)
|
||||
return res;
|
||||
spa_pod_parser_push(parser, frame, pod, parser->state.offset);
|
||||
parser->state.offset = parser->size;
|
||||
parser->state.offset += sizeof(struct spa_pod_object);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPA_API_POD_PARSER bool spa_pod_parser_can_collect(const struct spa_pod *pod, char type)
|
||||
SPA_API_POD_PARSER int spa_pod_parser_push_object_body(struct spa_pod_parser *parser,
|
||||
struct spa_pod_frame *frame, struct spa_pod_object *object, const void **object_body)
|
||||
{
|
||||
int res;
|
||||
struct spa_pod pod;
|
||||
const void *body;
|
||||
if ((res = spa_pod_parser_current_body(parser, &pod, &body)) < 0)
|
||||
return res;
|
||||
if ((res = spa_pod_body_get_object(&pod, body, object, object_body)) < 0)
|
||||
return res;
|
||||
spa_pod_parser_push(parser, frame, &pod, parser->state.offset);
|
||||
parser->state.offset += sizeof(struct spa_pod_object);
|
||||
return 0;
|
||||
}
|
||||
SPA_API_POD_PARSER int spa_pod_parser_push_object(struct spa_pod_parser *parser,
|
||||
struct spa_pod_frame *frame, uint32_t type, uint32_t *id)
|
||||
{
|
||||
int res;
|
||||
struct spa_pod_object obj;
|
||||
const void *obj_body;
|
||||
if ((res = spa_pod_parser_push_object_body(parser, frame, &obj, &obj_body)) < 0)
|
||||
return res;
|
||||
if (type != obj.body.type) {
|
||||
spa_pod_parser_unpush(parser, frame);
|
||||
return -EPROTO;
|
||||
}
|
||||
if (id != NULL)
|
||||
*id = obj.body.id;
|
||||
return 0;
|
||||
}
|
||||
SPA_API_POD_PARSER int spa_pod_parser_get_prop_body(struct spa_pod_parser *parser,
|
||||
struct spa_pod_prop *prop, const void **body)
|
||||
{
|
||||
int res;
|
||||
if ((res = spa_pod_parser_get_header(parser, prop,
|
||||
sizeof(struct spa_pod_prop),
|
||||
offsetof(struct spa_pod_prop, value), body)) >= 0)
|
||||
parser->state.offset += SPA_ROUND_UP_N(SPA_POD_PROP_SIZE(prop), SPA_POD_ALIGN);
|
||||
return res;
|
||||
}
|
||||
|
||||
SPA_API_POD_PARSER int spa_pod_parser_push_sequence_body(struct spa_pod_parser *parser,
|
||||
struct spa_pod_frame *frame, struct spa_pod_sequence *seq, const void **seq_body)
|
||||
{
|
||||
int res;
|
||||
struct spa_pod pod;
|
||||
const void *body;
|
||||
if ((res = spa_pod_parser_current_body(parser, &pod, &body)) < 0)
|
||||
return res;
|
||||
if ((res = spa_pod_body_get_sequence(&pod, body, seq, seq_body)) < 0)
|
||||
return res;
|
||||
spa_pod_parser_push(parser, frame, &pod, parser->state.offset);
|
||||
parser->state.offset += sizeof(struct spa_pod_sequence);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPA_API_POD_PARSER int spa_pod_parser_get_control_body(struct spa_pod_parser *parser,
|
||||
struct spa_pod_control *control, const void **body)
|
||||
{
|
||||
int res;
|
||||
if ((res = spa_pod_parser_get_header(parser, control,
|
||||
sizeof(struct spa_pod_control),
|
||||
offsetof(struct spa_pod_control, value), body)) >= 0)
|
||||
parser->state.offset += SPA_ROUND_UP_N(SPA_POD_CONTROL_SIZE(control), SPA_POD_ALIGN);
|
||||
return res;
|
||||
}
|
||||
|
||||
SPA_API_POD_PARSER int spa_pod_parser_object_find_prop(struct spa_pod_parser *parser,
|
||||
uint32_t key, struct spa_pod_prop *prop, const void **body)
|
||||
{
|
||||
uint32_t start_offset;
|
||||
struct spa_pod_frame *f = parser->state.frame;
|
||||
|
||||
if (f == NULL || f->pod.type != SPA_TYPE_Object)
|
||||
return -EINVAL;
|
||||
|
||||
start_offset = f->offset;
|
||||
while (spa_pod_parser_get_prop_body(parser, prop, body) >= 0) {
|
||||
if (prop->key == key)
|
||||
return 0;
|
||||
}
|
||||
spa_pod_parser_restart(parser, f);
|
||||
parser->state.offset += sizeof(struct spa_pod_object);
|
||||
while (parser->state.offset != start_offset &&
|
||||
spa_pod_parser_get_prop_body(parser, prop, body) >= 0) {
|
||||
if (prop->key == key)
|
||||
return 0;
|
||||
}
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
SPA_API_POD_PARSER bool spa_pod_parser_body_can_collect(const struct spa_pod *pod, const void *body, char type)
|
||||
{
|
||||
struct spa_pod_choice choice;
|
||||
|
||||
if (pod == NULL)
|
||||
return false;
|
||||
|
||||
|
|
@ -284,12 +508,11 @@ SPA_API_POD_PARSER bool spa_pod_parser_can_collect(const struct spa_pod *pod, ch
|
|||
return false;
|
||||
if (type == 'V')
|
||||
return true;
|
||||
if (SPA_POD_CHOICE_TYPE(pod) != SPA_CHOICE_None)
|
||||
if (spa_pod_body_get_choice(pod, body, &choice, &body) < 0)
|
||||
return false;
|
||||
if (pod->size - sizeof(struct spa_pod_choice_body) <
|
||||
SPA_POD_CHOICE_VALUE_SIZE(pod))
|
||||
if (choice.body.type != SPA_CHOICE_None)
|
||||
return false;
|
||||
pod = SPA_POD_CHOICE_CHILD(pod);
|
||||
pod = &choice.body.child;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
|
|
@ -334,72 +557,81 @@ SPA_API_POD_PARSER bool spa_pod_parser_can_collect(const struct spa_pod *pod, ch
|
|||
return false;
|
||||
}
|
||||
}
|
||||
SPA_API_POD_PARSER bool spa_pod_parser_can_collect(const struct spa_pod *pod, char type)
|
||||
{
|
||||
return spa_pod_parser_body_can_collect(pod, SPA_POD_BODY_CONST(pod), type);
|
||||
}
|
||||
|
||||
#define SPA_POD_PARSER_COLLECT(pod,_type,args) \
|
||||
#define SPA_POD_PARSER_COLLECT_BODY(pod,body,_type,args) \
|
||||
do { \
|
||||
switch (_type) { \
|
||||
case 'b': \
|
||||
*va_arg(args, bool*) = SPA_POD_VALUE(struct spa_pod_bool, pod); \
|
||||
*va_arg(args, bool*) = !!*((int32_t*)(body)); \
|
||||
break; \
|
||||
case 'I': \
|
||||
case 'i': \
|
||||
*va_arg(args, int32_t*) = SPA_POD_VALUE(struct spa_pod_int, pod); \
|
||||
*va_arg(args, int32_t*) = *((int32_t*)(body)); \
|
||||
break; \
|
||||
case 'l': \
|
||||
*va_arg(args, int64_t*) = SPA_POD_VALUE(struct spa_pod_long, pod); \
|
||||
*va_arg(args, int64_t*) = *((int64_t*)(body)); \
|
||||
break; \
|
||||
case 'f': \
|
||||
*va_arg(args, float*) = SPA_POD_VALUE(struct spa_pod_float, pod); \
|
||||
*va_arg(args, float*) = *((float*)(body)); \
|
||||
break; \
|
||||
case 'd': \
|
||||
*va_arg(args, double*) = SPA_POD_VALUE(struct spa_pod_double, pod); \
|
||||
*va_arg(args, double*) = *((double*)(body)); \
|
||||
break; \
|
||||
case 's': \
|
||||
*va_arg(args, char**) = \
|
||||
((pod) == NULL || (SPA_POD_TYPE(pod) == SPA_TYPE_None) \
|
||||
? NULL \
|
||||
: (char *)SPA_POD_CONTENTS(struct spa_pod_string, pod)); \
|
||||
*va_arg(args, char**) = ((pod)->type == SPA_TYPE_None) ? \
|
||||
NULL : (char *)(body); \
|
||||
break; \
|
||||
case 'S': \
|
||||
{ \
|
||||
char *dest = va_arg(args, char*); \
|
||||
uint32_t maxlen = va_arg(args, uint32_t); \
|
||||
strncpy(dest, (char *)SPA_POD_CONTENTS(struct spa_pod_string, pod), maxlen-1); \
|
||||
maxlen = SPA_MIN(maxlen, (pod)->size); \
|
||||
strncpy(dest, (char *)(body), maxlen-1); \
|
||||
dest[maxlen-1] = '\0'; \
|
||||
break; \
|
||||
} \
|
||||
case 'y': \
|
||||
*(va_arg(args, void **)) = SPA_POD_CONTENTS(struct spa_pod_bytes, pod); \
|
||||
*(va_arg(args, uint32_t *)) = SPA_POD_BODY_SIZE(pod); \
|
||||
*(va_arg(args, void **)) = (void*)(body); \
|
||||
*(va_arg(args, uint32_t *)) = (pod)->size; \
|
||||
break; \
|
||||
case 'R': \
|
||||
*va_arg(args, struct spa_rectangle*) = \
|
||||
SPA_POD_VALUE(struct spa_pod_rectangle, pod); \
|
||||
*((struct spa_rectangle*)(body)); \
|
||||
break; \
|
||||
case 'F': \
|
||||
*va_arg(args, struct spa_fraction*) = \
|
||||
SPA_POD_VALUE(struct spa_pod_fraction, pod); \
|
||||
*((struct spa_fraction*)(body)); \
|
||||
break; \
|
||||
case 'B': \
|
||||
*va_arg(args, uint32_t **) = \
|
||||
(uint32_t *) SPA_POD_CONTENTS(struct spa_pod_bitmap, pod); \
|
||||
*va_arg(args, uint32_t **) = (uint32_t*)(body); \
|
||||
break; \
|
||||
case 'a': \
|
||||
*va_arg(args, uint32_t*) = SPA_POD_ARRAY_VALUE_SIZE(pod); \
|
||||
*va_arg(args, uint32_t*) = SPA_POD_ARRAY_VALUE_TYPE(pod); \
|
||||
*va_arg(args, uint32_t*) = SPA_POD_ARRAY_N_VALUES(pod); \
|
||||
*va_arg(args, void**) = SPA_POD_ARRAY_VALUES(pod); \
|
||||
{ \
|
||||
struct spa_pod_array_body *b = \
|
||||
(struct spa_pod_array_body*)(body); \
|
||||
uint32_t child_size = b->child.size; \
|
||||
*va_arg(args, uint32_t*) = child_size; \
|
||||
*va_arg(args, uint32_t*) = b->child.type; \
|
||||
*va_arg(args, uint32_t*) = child_size ? \
|
||||
((pod)->size - sizeof(struct spa_pod_array_body))/child_size : 0; \
|
||||
*va_arg(args, void**) = SPA_PTROFF(b, \
|
||||
sizeof(struct spa_pod_array_body), void); \
|
||||
break; \
|
||||
} \
|
||||
case 'p': \
|
||||
{ \
|
||||
struct spa_pod_pointer_body *b = \
|
||||
(struct spa_pod_pointer_body *) SPA_POD_BODY(pod); \
|
||||
(struct spa_pod_pointer_body *)(body); \
|
||||
*(va_arg(args, uint32_t *)) = b->type; \
|
||||
*(va_arg(args, const void **)) = b->value; \
|
||||
break; \
|
||||
} \
|
||||
case 'h': \
|
||||
*va_arg(args, int64_t*) = SPA_POD_VALUE(struct spa_pod_fd, pod); \
|
||||
*va_arg(args, int64_t*) = *((int64_t*)(body)); \
|
||||
break; \
|
||||
case 'P': \
|
||||
case 'T': \
|
||||
|
|
@ -408,8 +640,8 @@ do { \
|
|||
{ \
|
||||
const struct spa_pod **d = va_arg(args, const struct spa_pod**); \
|
||||
if (d) \
|
||||
*d = ((pod) == NULL || (SPA_POD_TYPE(pod) == SPA_TYPE_None) \
|
||||
? NULL : (pod)); \
|
||||
*d = ((pod)->type == SPA_TYPE_None) ? \
|
||||
NULL : SPA_PTROFF((body), -sizeof(struct spa_pod), const struct spa_pod); \
|
||||
break; \
|
||||
} \
|
||||
default: \
|
||||
|
|
@ -417,6 +649,9 @@ do { \
|
|||
} \
|
||||
} while(false)
|
||||
|
||||
#define SPA_POD_PARSER_COLLECT(pod,_type,args) \
|
||||
SPA_POD_PARSER_COLLECT_BODY(pod, SPA_POD_BODY_CONST(pod),_type,args)
|
||||
|
||||
#define SPA_POD_PARSER_SKIP(_type,args) \
|
||||
do { \
|
||||
switch (_type) { \
|
||||
|
|
@ -455,49 +690,58 @@ do { \
|
|||
SPA_API_POD_PARSER int spa_pod_parser_getv(struct spa_pod_parser *parser, va_list args)
|
||||
{
|
||||
struct spa_pod_frame *f = parser->state.frame;
|
||||
uint32_t ftype = f ? f->pod.type : (uint32_t)SPA_TYPE_Struct;
|
||||
const struct spa_pod_prop *prop = NULL;
|
||||
int count = 0;
|
||||
|
||||
do {
|
||||
bool optional;
|
||||
const struct spa_pod *pod = NULL;
|
||||
const char *format;
|
||||
if (f == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
if (f && ftype == SPA_TYPE_Object) {
|
||||
do {
|
||||
bool optional, have_pod = false;
|
||||
struct spa_pod pod;
|
||||
const void *body = NULL;
|
||||
const char *format;
|
||||
struct spa_pod_prop prop;
|
||||
|
||||
if (f->pod.type == SPA_TYPE_Object) {
|
||||
uint32_t key = va_arg(args, uint32_t);
|
||||
const struct spa_pod_object *object;
|
||||
|
||||
if (key == 0)
|
||||
break;
|
||||
|
||||
object = (const struct spa_pod_object *)spa_pod_parser_frame(parser, f);
|
||||
prop = spa_pod_object_find_prop(object, prop, key);
|
||||
pod = prop ? &prop->value : NULL;
|
||||
if (spa_pod_parser_object_find_prop(parser, key, &prop, &body) >= 0) {
|
||||
pod = prop.value;
|
||||
have_pod = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ((format = va_arg(args, char *)) == NULL)
|
||||
break;
|
||||
|
||||
if (ftype == SPA_TYPE_Struct)
|
||||
pod = spa_pod_parser_next(parser);
|
||||
if (f->pod.type == SPA_TYPE_Struct)
|
||||
if (spa_pod_parser_next_body(parser, &pod, &body) >= 0)
|
||||
have_pod = true;
|
||||
|
||||
if ((optional = (*format == '?')))
|
||||
format++;
|
||||
|
||||
if (!spa_pod_parser_can_collect(pod, *format)) {
|
||||
if (!have_pod || !spa_pod_parser_body_can_collect(&pod, body, *format)) {
|
||||
if (!optional) {
|
||||
if (pod == NULL)
|
||||
if (!have_pod)
|
||||
return -ESRCH;
|
||||
else
|
||||
return -EPROTO;
|
||||
}
|
||||
SPA_POD_PARSER_SKIP(*format, args);
|
||||
} else {
|
||||
if (pod->type == SPA_TYPE_Choice && *format != 'V')
|
||||
pod = SPA_POD_CHOICE_CHILD(pod);
|
||||
struct spa_pod_choice choice;
|
||||
|
||||
SPA_POD_PARSER_COLLECT(pod, *format, args);
|
||||
if (pod.type == SPA_TYPE_Choice && *format != 'V') {
|
||||
if (spa_pod_body_get_choice(&pod, body, &choice, &body) < 0)
|
||||
return -EINVAL;
|
||||
pod = choice.body.child;
|
||||
}
|
||||
|
||||
SPA_POD_PARSER_COLLECT_BODY(&pod, body, *format, args);
|
||||
count++;
|
||||
}
|
||||
} while (true);
|
||||
|
|
|
|||
|
|
@ -30,6 +30,15 @@ extern "C" {
|
|||
#define SPA_POD_BODY(pod) SPA_PTROFF((pod),sizeof(struct spa_pod),void)
|
||||
#define SPA_POD_BODY_CONST(pod) SPA_PTROFF((pod),sizeof(struct spa_pod),const void)
|
||||
|
||||
#define SPA_POD_IS_VALID(pod) \
|
||||
(SPA_POD_BODY_SIZE(pod) < SPA_POD_MAX_SIZE)
|
||||
#define SPA_POD_CHECK_TYPE(pod,_type) \
|
||||
(SPA_POD_IS_VALID(pod) && \
|
||||
(pod)->type == (_type))
|
||||
#define SPA_POD_CHECK(pod,_type,_size) \
|
||||
(SPA_POD_CHECK_TYPE(pod,_type) && (pod)->size >= (_size))
|
||||
|
||||
|
||||
struct spa_pod {
|
||||
uint32_t size; /* size of the body */
|
||||
uint32_t type; /* a basic id of enum spa_type */
|
||||
|
|
|
|||
|
|
@ -129,6 +129,7 @@
|
|||
#include <spa/pod/dynamic.h>
|
||||
#include <spa/pod/event.h>
|
||||
#include <spa/pod/filter.h>
|
||||
#include <spa/pod/body.h>
|
||||
#include <spa/pod/iter.h>
|
||||
#include <spa/pod/parser.h>
|
||||
#include <spa/pod/pod.h>
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include <unistd.h>
|
||||
|
||||
#include <spa/param/video/format.h>
|
||||
#include <spa/pod/iter.h>
|
||||
#include <spa/pod/builder.h>
|
||||
#include <spa/utils/result.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@
|
|||
#include <sys/ucred.h>
|
||||
#endif
|
||||
|
||||
#include <spa/pod/iter.h>
|
||||
#include <spa/pod/parser.h>
|
||||
#include <spa/pod/builder.h>
|
||||
#include <spa/utils/cleanup.h>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#include <spa/node/utils.h>
|
||||
#include <spa/pod/parser.h>
|
||||
#include <spa/pod/iter.h>
|
||||
#include <spa/param/param.h>
|
||||
#include <spa/buffer/alloc.h>
|
||||
#include <spa/debug/types.h>
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include <spa/utils/result.h>
|
||||
#include <spa/utils/string.h>
|
||||
#include <spa/utils/json.h>
|
||||
#include <spa/pod/iter.h>
|
||||
#include <spa/pod/parser.h>
|
||||
#include <spa/debug/types.h>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue