blob: daedc7940c0ac0002f1158d72a4c37628d8fd490 [file] [log] [blame]
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <webrtc/SDP.h>
#include "Utils.h"
#include <android-base/logging.h>
#include <cerrno>
#include <iostream>
SDP::SDP()
: mInitCheck(-ENODEV),
mNewSectionEditorActive(false) {
}
int SDP::initCheck() const {
return mInitCheck;
}
size_t SDP::countSections() const {
CHECK(!mInitCheck);
return mLineIndexBySection.size();
}
void SDP::clear() {
mInitCheck = -ENODEV;
mLines.clear();
mLineIndexBySection.clear();
}
int SDP::setTo(const std::string &data) {
clear();
mLines = SplitString(data, "\r\n");
LOG(VERBOSE) << "SDP contained " << mLines.size() << " lines.";
mLineIndexBySection.push_back(0);
mInitCheck = 0;
for (size_t i = 0; i < mLines.size(); ++i) {
const auto &line = mLines[i];
LOG(VERBOSE) << "Line #" << i << ": " << line;
if (i == 0 && line != "v=0") {
mInitCheck = -EINVAL;
break;
}
if (line.size() < 2 || line[1] != '=') {
mInitCheck = -EINVAL;
break;
}
if (line[0] == 'm') {
mLineIndexBySection.push_back(i);
}
}
return mInitCheck;
}
void SDP::getSectionRange(
size_t section, size_t *lineStartIndex, size_t *lineStopIndex) const {
CHECK(!mInitCheck);
CHECK_LT(section, mLineIndexBySection.size());
if (lineStartIndex) {
*lineStartIndex = mLineIndexBySection[section];
}
if (lineStopIndex) {
if (section + 1 < mLineIndexBySection.size()) {
*lineStopIndex = mLineIndexBySection[section + 1];
} else {
*lineStopIndex = mLines.size();
}
}
}
std::vector<std::string>::const_iterator SDP::section_begin(
size_t section) const {
size_t startLineIndex;
getSectionRange(section, &startLineIndex, nullptr /* lineStopIndex */);
return mLines.cbegin() + startLineIndex;
}
std::vector<std::string>::const_iterator SDP::section_end(
size_t section) const {
size_t stopLineIndex;
getSectionRange(section, nullptr /* lineStartIndex */, &stopLineIndex);
return mLines.cbegin() + stopLineIndex;
}
SDP::SectionEditor SDP::createSection() {
CHECK(!mNewSectionEditorActive);
mNewSectionEditorActive = true;
if (mInitCheck) {
clear();
mInitCheck = 0;
}
return SectionEditor(this, countSections());
}
SDP::SectionEditor SDP::appendToSection(size_t section) {
CHECK_LT(section, countSections());
return SectionEditor(this, section);
}
void SDP::commitSectionEdit(
size_t section, const std::vector<std::string> &lines) {
CHECK_LE(section, countSections());
if (section == countSections()) {
// This was an edit creating a new section.
mLineIndexBySection.push_back(mLines.size());
mLines.insert(mLines.end(), lines.begin(), lines.end());
mNewSectionEditorActive = false;
return;
}
mLines.insert(section_end(section), lines.begin(), lines.end());
if (section + 1 < countSections()) {
mLineIndexBySection[section + 1] += lines.size();
}
}
////////////////////////////////////////////////////////////////////////////////
SDP::SectionEditor::SectionEditor(SDP *sdp, size_t section)
: mSDP(sdp),
mSection(section) {
}
SDP::SectionEditor::~SectionEditor() {
commit();
}
SDP::SectionEditor &SDP::SectionEditor::operator<<(std::string_view s) {
mBuffer.append(s);
return *this;
}
void SDP::SectionEditor::commit() {
if (mSDP) {
auto lines = SplitString(mBuffer, "\r\n");
mSDP->commitSectionEdit(mSection, lines);
mSDP = nullptr;
}
}