1/*
2 * libjingle
3 * Copyright 2010, Google Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 *  1. Redistributions of source code must retain the above copyright notice,
9 *     this list of conditions and the following disclaimer.
10 *  2. Redistributions in binary form must reproduce the above copyright notice,
11 *     this list of conditions and the following disclaimer in the documentation
12 *     and/or other materials provided with the distribution.
13 *  3. The name of the author may not be used to endorse or promote products
14 *     derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include "talk/p2p/base/sessiondescription.h"
29
30#include "talk/xmllite/xmlelement.h"
31
32namespace cricket {
33
34ContentInfo* FindContentInfoByName(
35    ContentInfos& contents, const std::string& name) {
36  for (ContentInfos::iterator content = contents.begin();
37       content != contents.end(); ++content) {
38    if (content->name == name) {
39      return &(*content);
40    }
41  }
42  return NULL;
43}
44
45const ContentInfo* FindContentInfoByName(
46    const ContentInfos& contents, const std::string& name) {
47  for (ContentInfos::const_iterator content = contents.begin();
48       content != contents.end(); ++content) {
49    if (content->name == name) {
50      return &(*content);
51    }
52  }
53  return NULL;
54}
55
56const ContentInfo* FindContentInfoByType(
57    const ContentInfos& contents, const std::string& type) {
58  for (ContentInfos::const_iterator content = contents.begin();
59       content != contents.end(); ++content) {
60    if (content->type == type) {
61      return &(*content);
62    }
63  }
64  return NULL;
65}
66
67const std::string* ContentGroup::FirstContentName() const {
68  return (!content_names_.empty()) ? &(*content_names_.begin()) : NULL;
69}
70
71bool ContentGroup::HasContentName(const std::string& content_name) const {
72  return (std::find(content_names_.begin(), content_names_.end(),
73                    content_name) != content_names_.end());
74}
75
76void ContentGroup::AddContentName(const std::string& content_name) {
77  if (!HasContentName(content_name)) {
78    content_names_.push_back(content_name);
79  }
80}
81
82bool ContentGroup::RemoveContentName(const std::string& content_name) {
83  ContentNames::iterator iter = std::find(
84      content_names_.begin(), content_names_.end(), content_name);
85  if (iter == content_names_.end()) {
86    return false;
87  }
88  content_names_.erase(iter);
89  return true;
90}
91
92SessionDescription* SessionDescription::Copy() const {
93  SessionDescription* copy = new SessionDescription(*this);
94  // Copy all ContentDescriptions.
95  for (ContentInfos::iterator content = copy->contents_.begin();
96      content != copy->contents().end(); ++content) {
97    content->description = content->description->Copy();
98  }
99  return copy;
100}
101
102const ContentInfo* SessionDescription::GetContentByName(
103    const std::string& name) const {
104  return FindContentInfoByName(contents_, name);
105}
106
107ContentInfo* SessionDescription::GetContentByName(
108    const std::string& name)  {
109  return FindContentInfoByName(contents_, name);
110}
111
112const ContentDescription* SessionDescription::GetContentDescriptionByName(
113    const std::string& name) const {
114  const ContentInfo* cinfo = FindContentInfoByName(contents_, name);
115  if (cinfo == NULL) {
116    return NULL;
117  }
118
119  return cinfo->description;
120}
121
122ContentDescription* SessionDescription::GetContentDescriptionByName(
123    const std::string& name) {
124  ContentInfo* cinfo = FindContentInfoByName(contents_, name);
125  if (cinfo == NULL) {
126    return NULL;
127  }
128
129  return cinfo->description;
130}
131
132const ContentInfo* SessionDescription::FirstContentByType(
133    const std::string& type) const {
134  return FindContentInfoByType(contents_, type);
135}
136
137const ContentInfo* SessionDescription::FirstContent() const {
138  return (contents_.empty()) ? NULL : &(*contents_.begin());
139}
140
141void SessionDescription::AddContent(const std::string& name,
142                                    const std::string& type,
143                                    ContentDescription* description) {
144  contents_.push_back(ContentInfo(name, type, description));
145}
146
147void SessionDescription::AddContent(const std::string& name,
148                                    const std::string& type,
149                                    bool rejected,
150                                    ContentDescription* description) {
151  contents_.push_back(ContentInfo(name, type, rejected, description));
152}
153
154bool SessionDescription::RemoveContentByName(const std::string& name) {
155  for (ContentInfos::iterator content = contents_.begin();
156       content != contents_.end(); ++content) {
157    if (content->name == name) {
158      delete content->description;
159      contents_.erase(content);
160      return true;
161    }
162  }
163
164  return false;
165}
166
167bool SessionDescription::AddTransportInfo(const TransportInfo& transport_info) {
168  if (GetTransportInfoByName(transport_info.content_name) != NULL) {
169    return false;
170  }
171  transport_infos_.push_back(transport_info);
172  return true;
173}
174
175bool SessionDescription::RemoveTransportInfoByName(const std::string& name) {
176  for (TransportInfos::iterator transport_info = transport_infos_.begin();
177       transport_info != transport_infos_.end(); ++transport_info) {
178    if (transport_info->content_name == name) {
179      transport_infos_.erase(transport_info);
180      return true;
181    }
182  }
183  return false;
184}
185
186const TransportInfo* SessionDescription::GetTransportInfoByName(
187    const std::string& name) const {
188  for (TransportInfos::const_iterator iter = transport_infos_.begin();
189       iter != transport_infos_.end(); ++iter) {
190    if (iter->content_name == name) {
191      return &(*iter);
192    }
193  }
194  return NULL;
195}
196
197TransportInfo* SessionDescription::GetTransportInfoByName(
198    const std::string& name) {
199  for (TransportInfos::iterator iter = transport_infos_.begin();
200       iter != transport_infos_.end(); ++iter) {
201    if (iter->content_name == name) {
202      return &(*iter);
203    }
204  }
205  return NULL;
206}
207
208void SessionDescription::RemoveGroupByName(const std::string& name) {
209  for (ContentGroups::iterator iter = content_groups_.begin();
210       iter != content_groups_.end(); ++iter) {
211    if (iter->semantics() == name) {
212      content_groups_.erase(iter);
213      break;
214    }
215  }
216}
217
218bool SessionDescription::HasGroup(const std::string& name) const {
219  for (ContentGroups::const_iterator iter = content_groups_.begin();
220       iter != content_groups_.end(); ++iter) {
221    if (iter->semantics() == name) {
222      return true;
223    }
224  }
225  return false;
226}
227
228const ContentGroup* SessionDescription::GetGroupByName(
229    const std::string& name) const {
230  for (ContentGroups::const_iterator iter = content_groups_.begin();
231       iter != content_groups_.end(); ++iter) {
232    if (iter->semantics() == name) {
233      return &(*iter);
234    }
235  }
236  return NULL;
237}
238
239}  // namespace cricket
240