Skip to content

Commit

Permalink
Do not differentiate between empty and null span - rename macro. (Azu…
Browse files Browse the repository at this point in the history
…re#1168)

* Do not differentiate between empty and null span - rename macro.

* Update all code paths that relied on az_span_ptr == NULL to
differentiate between a null span and an empty span to use az_span_size
== 0.

* Add test for twin_parse_received_topic with incomplete received_topic.

* Update some doc comments.
  • Loading branch information
ahsonkhan authored Aug 31, 2020
1 parent cd1f2e7 commit 18bc763
Show file tree
Hide file tree
Showing 42 changed files with 328 additions and 280 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
- Rename `az_iot_hub_client_properties` to `az_iot_message_properties` and move it from `az_iot_hub_client.h` to `az_iot_common.h`.
- Remove `az_pair` from `az_iot_message_properties_next()` in favor of individual name and value `az_span` parameters.
- In `az_result.h`, rename `az_failed()` to `az_result_failed()` and `az_succeeded()` to `az_result_succeeded()`.
- Renamed the macro `AZ_SPAN_NULL` to `AZ_SPAN_EMPTY`.

### Bug Fixes

Expand Down
4 changes: 2 additions & 2 deletions sdk/docs/core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ Our SDK passes `az_span` instances to functions to ensure that a buffer’s addr

Since many of our SDK functions require `az_span` parameters, customers must know how to create `az_span` instances so that you can call functions in our SDK. Here are some examples.

Create an empty (or NULL) `az_span`:
Create an empty `az_span`:

```C
az_span span_null = AZ_SPAN_NULL; // size = 0
az_span empty_span = AZ_SPAN_EMPTY; // size = 0
```

Create an `az_span` expression from a byte buffer:
Expand Down
2 changes: 1 addition & 1 deletion sdk/inc/azure/core/az_credentials.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ typedef struct
* @param[in] tenant_id An Azure tenant ID.
* @param[in] client_id An Azure client ID.
* @param[in] client_secret An Azure client secret.
* @param[in] authority Authentication authority URL to set. Passing #AZ_SPAN_NULL initializes
* @param[in] authority Authentication authority URL to set. Passing #AZ_SPAN_EMPTY initializes
* credential with default authority (Azure AD global authority -
* "https://login.microsoftonline.com/")
*
Expand Down
2 changes: 1 addition & 1 deletion sdk/inc/azure/core/az_http.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ az_http_response_init(az_http_response* out_response, az_span buffer)
.http_response = buffer,
.written = 0,
.parser = {
.remaining = AZ_SPAN_NULL,
.remaining = AZ_SPAN_EMPTY,
.next_kind = _az_HTTP_RESPONSE_KIND_STATUS_LINE,
},
},
Expand Down
15 changes: 11 additions & 4 deletions sdk/inc/azure/core/az_json.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,11 @@ typedef struct

/// This read-only field gives access to the slice of the JSON text that represents the token
/// value, and it shouldn't be modified by the caller.
/// If the token straddles non-contiguous buffers, this is set to #AZ_SPAN_NULL.
/// If the token straddles non-contiguous buffers, this is set to the partial token value
/// available in the last segment.
/// The user can call #az_json_token_copy_into_span() to get the token value into a contiguous
/// buffer. In the case of JSON strings, the slice does not include the surrounding quotes.
/// buffer.
/// In the case of JSON strings, the slice does not include the surrounding quotes.
az_span slice;

/// This read-only field gives access to the size of the JSON text slice that represents the token
Expand All @@ -86,12 +88,17 @@ typedef struct

struct
{
/// A flag to indicate whether the JSON token straddles more than one buffer segment and is
/// split amongst non-contiguous buffers. For tokens created from input JSON payloads within a
/// contiguous buffer, this field is always false.
bool is_multisegment;

/// A flag to indicate whether the JSON string contained any escaped characters, used as an
/// optimization to avoid redundant checks. It is meaningless for any other token kind.
bool string_has_escaped_chars;

/// This is the first segment in the entire JSON payload, if it was non-contiguous. Otherwise,
/// its set to #AZ_SPAN_NULL.
/// its set to #AZ_SPAN_EMPTY.
az_span* pointer_to_first_buffer;

/// The segment index within the non-contiguous JSON payload where this token starts.
Expand Down Expand Up @@ -385,7 +392,7 @@ az_json_writer_get_bytes_used_in_destination(az_json_writer const* json_writer)
* @param[in] value The UTF-8 encoded value to be written as a JSON string. The value is escaped
* before writing.
*
* @remarks If \p value is #AZ_SPAN_NULL, the empty JSON string value is written (i.e. "").
* @remarks If \p value is #AZ_SPAN_EMPTY, the empty JSON string value is written (i.e. "").
*
* @return An #az_result value indicating the result of the operation.
* @retval #AZ_OK The string value was appended successfully.
Expand Down
9 changes: 6 additions & 3 deletions sdk/inc/azure/core/az_span.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,13 @@ AZ_NODISCARD az_span az_span_create(uint8_t* ptr, int32_t size);

/**
* @brief An empty #az_span.
*
* @remark There is no guarantee that the pointer backing this span will be `NULL` and the caller
* shouldn't rely on it. However, the size will be 0.
*/
// When updating this macro, also update AZ_PAIR_NULL, which should be using this macro, but can't
// due to warnings, and so it is using an expansion of this macro instead.
#define AZ_SPAN_NULL \
#define AZ_SPAN_EMPTY \
(az_span) \
{ \
._internal = {.ptr = NULL, .size = 0 } \
Expand Down Expand Up @@ -275,7 +278,7 @@ AZ_NODISCARD int32_t az_span_find(az_span source, az_span target);
* source.
*
* @remarks This function copies all of \p source into the \p destination even if they overlap.
* @remarks If \p source is an empty #az_span or #AZ_SPAN_NULL, this function will just return
* @remarks If \p source is an empty #az_span or #AZ_SPAN_EMPTY, this function will just return
* \p destination.
*/
az_span az_span_copy(az_span destination, az_span source);
Expand Down Expand Up @@ -536,7 +539,7 @@ typedef struct
} az_pair;

/**
* @brief An #az_pair instance whose key and value fields are initialized to #AZ_SPAN_NULL.
* @brief An #az_pair instance whose key and value fields are initialized to #AZ_SPAN_EMPTY.
*/
#define AZ_PAIR_NULL \
(az_pair) \
Expand Down
6 changes: 3 additions & 3 deletions sdk/inc/azure/core/internal/az_http_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ _az_http_policy_apiversion_options_default()
{
return (_az_http_policy_apiversion_options){
._internal = { .option_location = _az_http_policy_apiversion_option_location_header,
.name = AZ_SPAN_NULL,
.version = AZ_SPAN_NULL }
.name = AZ_SPAN_EMPTY,
.version = AZ_SPAN_EMPTY }
};
}

Expand Down Expand Up @@ -168,7 +168,7 @@ AZ_NODISCARD AZ_INLINE az_result _az_http_pipeline_nextpolicy(
* @param[in] url_length The size of the initial url value within url #az_span.
* @param[in] headers_buffer The #az_span to be used for storing headers for the request. The total
* number of headers are calculated automatically based on the size of the buffer.
* @param[in] body The #az_span buffer that contains a payload for the request. Use #AZ_SPAN_NULL
* @param[in] body The #az_span buffer that contains a payload for the request. Use #AZ_SPAN_EMPTY
* for requests that don't have a body.
*
* @return
Expand Down
11 changes: 9 additions & 2 deletions sdk/inc/azure/core/internal/az_span_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,18 @@ AZ_NODISCARD int32_t _az_span_url_encode_calc_length(az_span source);
* @param[out] out_remainder The #az_span pointing to the remaining bytes in `source`, starting
* after the occurrence of `delimiter`. If the position after `delimiter` is the end of `source`,
* `out_remainder` is set to an empty #az_span.
* @param[out] out_index The position of \p delimiter in \p source if \p source contains the \p
* delimiter within it. Otherwise, it is set to -1.
*
* @return The #az_span pointing to the token delimited by the beginning of `source` up to the first
* occurrence of (but not including the) `delimiter`, or the end of `source` if `delimiter` is not
* found. If `source` is empty, AZ_SPAN_NULL is returned instead.
* found. If `source` is empty, #AZ_SPAN_EMPTY is returned instead.
*/
AZ_NODISCARD az_span _az_span_token(az_span source, az_span delimiter, az_span* out_remainder);
az_span _az_span_token(
az_span source,
az_span delimiter,
az_span* out_remainder,
int32_t* out_index);

#include <azure/core/_az_cfg_suffix.h>

Expand Down
2 changes: 1 addition & 1 deletion sdk/samples/iot/aziot_esp8266/aziot_esp8266.ino
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ static int generateSasToken(char* sas_token, size_t size)
&client,
b64enc_hmacsha256_signature_span,
expiration,
AZ_SPAN_NULL,
AZ_SPAN_EMPTY,
sas_token,
size,
NULL)))
Expand Down
8 changes: 4 additions & 4 deletions sdk/samples/iot/paho_iot_hub_pnp_component_sample.c
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,7 @@ static void send_device_serial_number(void)
// Build the serial number reported property message.
rc = pnp_create_reported_property(
mqtt_message.payload_span,
AZ_SPAN_NULL,
AZ_SPAN_EMPTY,
reported_serial_num_property_name,
append_string_callback,
(void*)&reported_serial_num_property_value,
Expand Down Expand Up @@ -532,7 +532,7 @@ static void request_device_twin_document(void)
}

// Publish the twin document request.
mqtt_publish_message(mqtt_message.topic, AZ_SPAN_NULL, MQTT_PUBLISH_QOS);
mqtt_publish_message(mqtt_message.topic, AZ_SPAN_EMPTY, MQTT_PUBLISH_QOS);
IOT_SAMPLE_LOG_SUCCESS("Client requested twin document.");
IOT_SAMPLE_LOG(" "); // Formatting.

Expand Down Expand Up @@ -898,7 +898,7 @@ static az_result temp_controller_get_telemetry_message(pnp_mqtt_message* message

// Get the Telemetry topic to publish the telemetry messages.
rc = pnp_get_telemetry_topic(
&hub_client, NULL, AZ_SPAN_NULL, message->topic, message->topic_length, NULL);
&hub_client, NULL, AZ_SPAN_EMPTY, message->topic, message->topic_length, NULL);
if (az_result_failed(rc))
{
IOT_SAMPLE_LOG_ERROR(
Expand Down Expand Up @@ -962,7 +962,7 @@ static void property_callback(
az_result rc;
(void)user_context_callback;

if (az_span_ptr(component_name) == NULL || az_span_size(component_name) == 0)
if (az_span_size(component_name) == 0)
{
IOT_SAMPLE_LOG_ERROR(
"Temperature Controller does not support writable property \"%.*s\". All writeable "
Expand Down
13 changes: 7 additions & 6 deletions sdk/samples/iot/paho_iot_hub_pnp_sample.c
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,7 @@ static void request_device_twin_document(void)
}

// Publish the twin document request.
mqtt_publish_message(twin_document_topic_buffer, AZ_SPAN_NULL, SAMPLE_PUBLISH_QOS);
mqtt_publish_message(twin_document_topic_buffer, AZ_SPAN_EMPTY, SAMPLE_PUBLISH_QOS);
}

static void receive_messages(void)
Expand Down Expand Up @@ -852,18 +852,19 @@ static az_result invoke_getMaxMinReport(
command_start_time_value_buffer,
sizeof(command_start_time_value_buffer),
&incoming_since_value_len));
az_span start_time_span
= az_span_create((uint8_t*)command_start_time_value_buffer, incoming_since_value_len);

IOT_SAMPLE_LOG_AZ_SPAN("start time:", start_time_span);

// Set the response payload to error if the "since" value was empty.
if (az_span_ptr(start_time_span) == NULL)
if (incoming_since_value_len == 0)
{
*out_response = command_empty_response_payload;
return AZ_ERROR_ITEM_NOT_FOUND;
}

az_span start_time_span
= az_span_create((uint8_t*)command_start_time_value_buffer, incoming_since_value_len);

IOT_SAMPLE_LOG_AZ_SPAN("start time:", start_time_span);

// Get the current time as a string.
time_t rawtime;
struct tm* timeinfo;
Expand Down
2 changes: 1 addition & 1 deletion sdk/samples/iot/paho_iot_hub_sas_telemetry_sample.c
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ static void generate_sas_key(void)
&hub_client,
sas_base64_encoded_signed_signature,
sas_duration,
AZ_SPAN_NULL,
AZ_SPAN_EMPTY,
mqtt_password_buffer,
sizeof(mqtt_password_buffer),
&mqtt_password_length);
Expand Down
2 changes: 1 addition & 1 deletion sdk/samples/iot/paho_iot_provisioning_sas_sample.c
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,7 @@ static void generate_sas_key(void)
&provisioning_client,
sas_base64_encoded_signed_signature,
sas_duration,
AZ_SPAN_NULL,
AZ_SPAN_EMPTY,
mqtt_password_buffer,
sizeof(mqtt_password_buffer),
&mqtt_password_length);
Expand Down
20 changes: 10 additions & 10 deletions sdk/samples/iot/pnp/pnp_protocol.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ static az_result is_component_in_model(
{
int32_t index = 0;

if (az_span_ptr(component_name) == NULL || az_span_size(component_name) == 0)
if (az_span_size(component_name) == 0)
{
return AZ_ERROR_UNEXPECTED_CHAR;
}
Expand Down Expand Up @@ -154,7 +154,7 @@ az_result pnp_get_telemetry_topic(
{
az_iot_message_properties pnp_properties;

if (az_span_ptr(component_name) != NULL)
if (az_span_size(component_name) != 0)
{
if (properties == NULL)
{
Expand All @@ -170,7 +170,7 @@ az_result pnp_get_telemetry_topic(

IOT_SAMPLE_RETURN_IF_FAILED(az_iot_hub_client_telemetry_get_publish_topic(
client,
az_span_ptr(component_name) != NULL ? properties : NULL,
az_span_size(component_name) != 0 ? properties : NULL,
mqtt_topic,
mqtt_topic_size,
out_mqtt_topic_length));
Expand All @@ -193,7 +193,7 @@ void pnp_parse_command_name(
}
else
{
*component_name = AZ_SPAN_NULL;
*component_name = AZ_SPAN_EMPTY;
*pnp_command_name = component_command;
}
}
Expand All @@ -212,7 +212,7 @@ az_result pnp_create_reported_property(

IOT_SAMPLE_RETURN_IF_FAILED(az_json_writer_append_begin_object(&jw));

if (az_span_ptr(component_name) != NULL)
if (az_span_size(component_name) != 0)
{
IOT_SAMPLE_RETURN_IF_FAILED(az_json_writer_append_property_name(&jw, component_name));
IOT_SAMPLE_RETURN_IF_FAILED(az_json_writer_append_begin_object(&jw));
Expand All @@ -223,7 +223,7 @@ az_result pnp_create_reported_property(
IOT_SAMPLE_RETURN_IF_FAILED(az_json_writer_append_property_name(&jw, property_name));
IOT_SAMPLE_RETURN_IF_FAILED(append_callback(&jw, context));

if (az_span_ptr(component_name) != NULL)
if (az_span_size(component_name) != 0)
{
IOT_SAMPLE_RETURN_IF_FAILED(az_json_writer_append_end_object(&jw));
}
Expand Down Expand Up @@ -251,7 +251,7 @@ az_result pnp_create_reported_property_with_status(

IOT_SAMPLE_RETURN_IF_FAILED(az_json_writer_init(&jw, json_buffer, NULL));
IOT_SAMPLE_RETURN_IF_FAILED(az_json_writer_append_begin_object(&jw));
if (az_span_ptr(component_name) != NULL)
if (az_span_size(component_name) != 0)
{
IOT_SAMPLE_RETURN_IF_FAILED(az_json_writer_append_property_name(&jw, component_name));
IOT_SAMPLE_RETURN_IF_FAILED(az_json_writer_append_begin_object(&jw));
Expand All @@ -270,7 +270,7 @@ az_result pnp_create_reported_property_with_status(
az_json_writer_append_property_name(&jw, desired_temp_ack_version_name));
IOT_SAMPLE_RETURN_IF_FAILED(az_json_writer_append_int32(&jw, ack_version));

if (az_span_ptr(ack_description) != NULL)
if (az_span_size(ack_description) != 0)
{
IOT_SAMPLE_RETURN_IF_FAILED(
az_json_writer_append_property_name(&jw, desired_temp_ack_description_name));
Expand All @@ -280,7 +280,7 @@ az_result pnp_create_reported_property_with_status(
IOT_SAMPLE_RETURN_IF_FAILED(az_json_writer_append_end_object(&jw));
IOT_SAMPLE_RETURN_IF_FAILED(az_json_writer_append_end_object(&jw));

if (az_span_ptr(component_name) != NULL)
if (az_span_size(component_name) != 0)
{
IOT_SAMPLE_RETURN_IF_FAILED(az_json_writer_append_end_object(&jw));
}
Expand Down Expand Up @@ -358,7 +358,7 @@ az_result pnp_process_device_twin_message(
}
else
{
property_callback(AZ_SPAN_NULL, &property_name, jr, version, context_ptr);
property_callback(AZ_SPAN_EMPTY, &property_name, jr, version, context_ptr);
}
}
else if (jr.token.kind == AZ_JSON_TOKEN_BEGIN_OBJECT)
Expand Down
9 changes: 5 additions & 4 deletions sdk/samples/iot/pnp/pnp_thermostat_component.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ static az_result invoke_getMaxMinReport(
{
// az_result result;
// Parse the "since" field in the payload.
az_span start_time_span = AZ_SPAN_NULL;
az_span start_time_span = AZ_SPAN_EMPTY;
az_json_reader jr;
IOT_SAMPLE_RETURN_IF_FAILED(az_json_reader_init(&jr, payload, NULL));
IOT_SAMPLE_RETURN_IF_FAILED(az_json_reader_next_token(&jr));
Expand All @@ -121,16 +121,17 @@ static az_result invoke_getMaxMinReport(
incoming_since_value_buffer,
sizeof(incoming_since_value_buffer),
&incoming_since_value_buffer_len));
start_time_span
= az_span_create((uint8_t*)incoming_since_value_buffer, incoming_since_value_buffer_len);

// Set the response payload to error if the "since" field was not sent
if (az_span_ptr(start_time_span) == NULL)
if (incoming_since_value_buffer_len == 0)
{
response = report_error_payload;
return AZ_ERROR_ITEM_NOT_FOUND;
}

start_time_span
= az_span_create((uint8_t*)incoming_since_value_buffer, incoming_since_value_buffer_len);

// Get the current time as a string
time_t rawtime;
struct tm* timeinfo;
Expand Down
Loading

0 comments on commit 18bc763

Please sign in to comment.