blob: a1cf2b431931a662f657e2204b01e956db0c1a2d [file] [log] [blame]
/*
* Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_FIELD_ENCODING_PARSER_H_
#define LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_FIELD_ENCODING_PARSER_H_
#include <string>
#include <vector>
#include "logging/rtc_event_log/events/rtc_event_field_encoding.h"
// TODO(terelius): Compared to a generic 'Status' class, this
// class allows us additional information about the context
// in which the error occurred. This is currently limited to
// the source location (file and line), but we plan on adding
// information about the event and field name being parsed.
// If/when we start using absl::Status in WebRTC, consider
// whether payloads would be an appropriate alternative.
class RtcEventLogParseStatus {
public:
static RtcEventLogParseStatus Success() { return RtcEventLogParseStatus(); }
static RtcEventLogParseStatus Error(std::string error,
std::string file,
int line) {
return RtcEventLogParseStatus(error, file, line);
}
bool ok() const { return error_.empty(); }
std::string message() const { return error_; }
private:
RtcEventLogParseStatus() : error_() {}
RtcEventLogParseStatus(std::string error, std::string file, int line)
: error_(error + " (" + file + ": " + std::to_string(line) + ")") {}
std::string error_;
};
namespace webrtc {
class EventParser {
public:
EventParser() = default;
// N.B: This method stores a abls::string_view into the string to be
// parsed. The caller is responsible for ensuring that the actual string
// remains unmodified and outlives the EventParser.
RtcEventLogParseStatus Initialize(absl::string_view s, bool batched);
// Attempts to parse the field specified by `params`, skipping past
// other fields that may occur before it. Returns
// RtcEventLogParseStatus::Success() and populates `values` (and `positions`)
// if the field is found. Returns RtcEventLogParseStatus::Success() and clears
// `values` (and `positions`) if the field doesn't exist. Returns a
// RtcEventLogParseStatus::Error if the log is incomplete, malformed or
// otherwise can't be parsed. `values` and `positions` are pure out-parameters
// that allow the caller to reuse the same temporary storage for all fields.
// Any previous content in the out parameters is cleared.
RtcEventLogParseStatus ParseField(const FieldParameters& params,
std::vector<uint64_t>* values,
std::vector<bool>* positions = nullptr);
// Number of events in a batch.
uint64_t NumEventsInBatch() const { return num_events_; }
// Bytes remaining in `pending_data_`. Assuming there are no unknown
// fields, BytesRemaining() should return 0 when all known fields
// in the event have been parsed.
size_t RemainingBytes() const { return pending_data_.size(); }
private:
uint64_t ReadLittleEndian(uint8_t bytes);
uint64_t ReadVarInt();
uint64_t ReadSingleValue(FieldType field_type);
uint64_t ReadOptionalValuePositions(std::vector<bool>* positions);
uint64_t CountAndIgnoreOptionalValuePositions();
void ReadDeltasAndPopulateValues(FixedLengthEncodingParametersV3 params,
uint64_t num_deltas,
const uint64_t base,
std::vector<uint64_t>* values);
void SetError() { error_ = true; }
bool Ok() const { return !error_; }
// String to be consumed.
absl::string_view pending_data_;
// Tracks whether an error has occurred in one of the helper
// functions above.
bool error_ = false;
uint64_t num_events_ = 1;
uint64_t last_field_id_ = FieldParameters::kTimestampField;
};
} // namespace webrtc
#endif // LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_FIELD_ENCODING_PARSER_H_