2017-09-14 16:15:24 +00:00
|
|
|
// Copyright 2017 Google Inc. All rights reserved.
|
|
|
|
//
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file or at
|
|
|
|
// https://developers.google.com/open-source/licenses/bsd
|
|
|
|
|
|
|
|
#include "packager/media/formats/webvtt/text_readers.h"
|
|
|
|
|
2020-06-30 21:31:07 +00:00
|
|
|
#include <cstring>
|
|
|
|
|
2017-09-14 16:15:24 +00:00
|
|
|
#include "packager/base/logging.h"
|
|
|
|
|
|
|
|
namespace shaka {
|
|
|
|
namespace media {
|
|
|
|
|
2020-06-30 21:31:07 +00:00
|
|
|
LineReader::LineReader() : should_flush_(false) {}
|
2017-09-14 16:15:24 +00:00
|
|
|
|
2020-06-30 21:31:07 +00:00
|
|
|
void LineReader::PushData(const uint8_t* data, size_t data_size) {
|
|
|
|
buffer_.Push(data, static_cast<int>(data_size));
|
|
|
|
should_flush_ = false;
|
2017-09-14 16:15:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Split lines based on https://w3c.github.io/webvtt/#webvtt-line-terminator
|
|
|
|
bool LineReader::Next(std::string* out) {
|
|
|
|
DCHECK(out);
|
2020-06-30 21:31:07 +00:00
|
|
|
|
|
|
|
int i;
|
|
|
|
int skip = 0;
|
|
|
|
const uint8_t* data;
|
|
|
|
int data_size;
|
|
|
|
buffer_.Peek(&data, &data_size);
|
|
|
|
for (i = 0; i < data_size; i++) {
|
|
|
|
// Handle \n
|
|
|
|
if (data[i] == '\n') {
|
|
|
|
skip = 1;
|
2017-09-14 16:15:24 +00:00
|
|
|
break;
|
|
|
|
}
|
2020-06-30 21:31:07 +00:00
|
|
|
|
|
|
|
// Handle \r and \r\n
|
|
|
|
if (data[i] == '\r') {
|
|
|
|
// Only read if we can see the next character; this ensures we don't get
|
|
|
|
// the '\n' in the next PushData.
|
|
|
|
if (i + 1 == data_size) {
|
|
|
|
if (!should_flush_)
|
|
|
|
return false;
|
|
|
|
skip = 1;
|
|
|
|
} else {
|
|
|
|
if (data[i + 1] == '\n')
|
|
|
|
skip = 2;
|
|
|
|
else
|
|
|
|
skip = 1;
|
2017-09-14 16:15:24 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2020-06-30 21:31:07 +00:00
|
|
|
|
|
|
|
if (i == data_size && (!should_flush_ || i == 0)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO(modmaker): Handle character encodings?
|
|
|
|
out->assign(data, data + i);
|
|
|
|
buffer_.Pop(i + skip);
|
|
|
|
return true;
|
2017-09-14 16:15:24 +00:00
|
|
|
}
|
|
|
|
|
2020-06-30 21:31:07 +00:00
|
|
|
void LineReader::Flush() {
|
|
|
|
should_flush_ = true;
|
|
|
|
}
|
2017-09-14 16:15:24 +00:00
|
|
|
|
2020-06-30 21:31:07 +00:00
|
|
|
BlockReader::BlockReader() : should_flush_(false) {}
|
2017-09-14 16:15:24 +00:00
|
|
|
|
2020-06-30 21:31:07 +00:00
|
|
|
void BlockReader::PushData(const uint8_t* data, size_t data_size) {
|
|
|
|
source_.PushData(data, data_size);
|
|
|
|
should_flush_ = false;
|
|
|
|
}
|
2017-09-14 16:15:24 +00:00
|
|
|
|
2020-06-30 21:31:07 +00:00
|
|
|
bool BlockReader::Next(std::vector<std::string>* out) {
|
|
|
|
DCHECK(out);
|
2017-09-14 16:15:24 +00:00
|
|
|
|
2020-06-30 21:31:07 +00:00
|
|
|
bool end_block = false;
|
2017-09-14 16:15:24 +00:00
|
|
|
// Read through lines until a non-empty line is found. With a non-empty
|
|
|
|
// line is found, start adding the lines to the output and once an empty
|
|
|
|
// line if found again, stop adding lines and exit.
|
|
|
|
std::string line;
|
|
|
|
while (source_.Next(&line)) {
|
2020-06-30 21:31:07 +00:00
|
|
|
if (!temp_.empty() && line.empty()) {
|
|
|
|
end_block = true;
|
2017-09-14 16:15:24 +00:00
|
|
|
break;
|
|
|
|
}
|
2020-06-30 21:31:07 +00:00
|
|
|
if (!line.empty()) {
|
|
|
|
temp_.emplace_back(std::move(line));
|
2017-09-14 16:15:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-30 21:31:07 +00:00
|
|
|
if (!end_block && (!should_flush_ || temp_.empty()))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
*out = std::move(temp_);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void BlockReader::Flush() {
|
|
|
|
source_.Flush();
|
|
|
|
should_flush_ = true;
|
2017-09-14 16:15:24 +00:00
|
|
|
}
|
2020-06-30 21:31:07 +00:00
|
|
|
|
2017-09-14 16:15:24 +00:00
|
|
|
} // namespace media
|
|
|
|
} // namespace shaka
|