Stroika Library 3.0d23x
 
Loading...
Searching...
No Matches
DeviceDescription.cpp
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2026. All rights reserved
3 */
4#include "Stroika/Frameworks/StroikaPreComp.h"
5
6#include <sstream>
7
10#include "Stroika/Foundation/DataExchange/StructuredStreamEvents/ObjectReader.h"
12#include "Stroika/Foundation/DataExchange/XML/WriterUtils.h"
16
17#include "DeviceDescription.h"
18
19// Comment this in to turn on aggressive noisy DbgTrace in this module
20// #define USE_NOISY_TRACE_IN_THIS_MODULE_ 1
21
22using std::byte;
23
24using namespace Stroika::Foundation;
26
27using Memory::MakeSharedPtr;
28
29using namespace Stroika::Frameworks;
30using namespace Stroika::Frameworks::UPnP;
31
32/*
33 ********************************************************************************
34 ************************* DeviceDescription::Icon ******************************
35 ********************************************************************************
36 */
38{
40 sb << "{"sv;
41 sb << "MimeType: "sv << fMimeType;
42 sb << ", HorizontalPixels: "sv << fHorizontalPixels;
43 sb << ", VerticalPixels: "sv << fVerticalPixels;
44 sb << ", ColorDepth : "sv << fColorDepth;
45 sb << ", URL: "sv << fURL;
46 sb << "}"sv;
47 return sb;
48}
49
50/*
51 ********************************************************************************
52 ************************ DeviceDescription::Service ****************************
53 ********************************************************************************
54 */
55String DeviceDescription::Service::ToString () const
56{
58 sb << "{"sv;
59 sb << "Service-ID: "sv << fServiceID;
60 sb << ", SCPD-URL: "sv << fSCPDURL;
61 sb << ", Control-URL: "sv << fControlURL;
62 sb << ", Event-Sub-URL: "sv << fEventSubURL;
63 sb << "}"sv;
64 return sb;
65}
66
67/*
68 ********************************************************************************
69 ******************************* DeviceDescription ******************************
70 ********************************************************************************
71 */
73{
75 sb << "{"sv;
76 if (fPresentationURL) {
77 sb << "Presentation-URL: "sv << fPresentationURL;
78 }
79 sb << ", Device-Type: "sv << fDeviceType;
80 sb << ", Manufacture-Name: "sv << fManufactureName;
81 sb << ", Friendly-Name: "sv << fFriendlyName;
82 if (fManufacturingURL) {
83 sb << ", Manufacturing-URL: "sv << fManufacturingURL;
84 }
85 if (fModelDescription) {
86 sb << ", Model-Description: "sv << fModelDescription;
87 }
88 sb << ", Model-Name: "sv << fModelName;
89 if (fModelNumber) {
90 sb << ", Model-Number: "sv << fModelNumber;
91 }
92 if (fModelURL) {
93 sb << ", Model-URL: "sv << *fModelURL;
94 }
95 if (fSerialNumber) {
96 sb << ", Serial-Number: "sv << fSerialNumber;
97 }
98 sb << ", UDN: "sv << fUDN;
99 if (fUPC) {
100 sb << ", UPC: "sv << fUPC;
101 }
102 if (fIcons) {
103 sb << ", Icons: "sv << fIcons;
104 }
105 if (fServices) {
106 sb << ", Services: "sv << fServices;
107 }
108 sb << "}"sv;
109 return sb;
110}
111
112ObjectVariantMapper DeviceDescription::mkMapper_ ()
113{
114 ObjectVariantMapper mapper;
115
116 mapper.AddClass<Icon> ({
117 {"mimetype"sv, &Icon::fMimeType},
118 {"width"sv, &Icon::fHorizontalPixels},
119 {"height"sv, &Icon::fVerticalPixels},
120 {"depth"sv, &Icon::fColorDepth},
121 {"url"sv, &Icon::fURL},
122 });
124 mapper.AddCommonType<optional<Collection<Icon>>> ();
125
126 mapper.AddClass<Service> ({
127 {"serviceType"sv, &Service::fServiceType},
128 {"serviceId"sv, &Service::fServiceID},
129 {"SCPDURL"sv, &Service::fSCPDURL},
130 {"controlURL"sv, &Service::fControlURL},
131 {"eventSubURL"sv, &Service::fEventSubURL},
132 });
134 mapper.AddCommonType<optional<Collection<Service>>> ();
135
136 mapper.AddCommonType<optional<String>> ();
137 mapper.AddCommonType<optional<URI>> ();
138
139 mapper.AddClass<DeviceDescription> ({
140 {"presentationURL"sv, &DeviceDescription::fPresentationURL},
141 {"deviceType"sv, &DeviceDescription::fDeviceType},
142 {"manufacturer"sv, &DeviceDescription::fManufactureName},
143 {"friendlyName"sv, &DeviceDescription::fFriendlyName},
144 {"manufacturerURL"sv, &DeviceDescription::fManufacturingURL},
145 {"modelDescription"sv, &DeviceDescription::fModelDescription},
146 {"modelName"sv, &DeviceDescription::fModelName},
147 {"modelNumber"sv, &DeviceDescription::fModelNumber},
148 {"modelURL"sv, &DeviceDescription::fModelURL},
149 {"serialNumber"sv, &DeviceDescription::fSerialNumber},
150 {"UDN"sv, &DeviceDescription::fUDN},
151 {"UPC"sv, &DeviceDescription::fUPC},
152 {"iconList"sv, &DeviceDescription::fIcons},
153 {"serviceList"sv, &DeviceDescription::fServices},
154 });
155 return mapper;
156};
157
158/*
159 ********************************************************************************
160 ********************************* UPnP::Serialize ******************************
161 ********************************************************************************
162 */
163Memory::BLOB UPnP::Serialize (const DeviceDescription& dd)
164{
165 using namespace DataExchange::XML;
166
167 /*
168 // very very rough prelim draft
169 *Example based on
170 http://upnp.org/specs/arch/UPnP-arch-DeviceArchitecture-v1.0.pdf
171 */
172 stringstream tmp;
173 tmp << "<?xml version=\"1.0\"?>" << endl;
174 tmp << "<root xmlns=\"urn:schemas-upnp-org:device-1-0\">" << endl;
175 tmp << " <specVersion>" << endl;
176 tmp << " <major>1</major>" << endl;
177 tmp << " <minor>0</minor>" << endl;
178 tmp << " </specVersion>" << endl;
179 tmp << " <device>" << endl;
180 tmp << " <deviceType>" << QuoteForXML (dd.fDeviceType) << "</deviceType>" << endl;
181 tmp << " <friendlyName>" << QuoteForXML (dd.fFriendlyName) << "</friendlyName>" << endl;
182 tmp << " <manufacturer>" << QuoteForXML (dd.fManufactureName) << "</manufacturer>" << endl;
183 if (dd.fManufacturingURL) {
184 tmp << " <manufacturerURL>" << QuoteForXML (dd.fManufacturingURL->As<String> ()) << "</manufacturerURL>" << endl;
185 }
186 if (dd.fModelDescription) {
187 tmp << " <modelDescription>" << QuoteForXML (dd.fModelDescription) << "</modelDescription>" << endl;
188 }
189 tmp << " <modelName>" << QuoteForXML (dd.fModelName) << "</modelName>" << endl;
190 if (dd.fModelNumber) {
191 tmp << " <modelNumber>" << QuoteForXML (dd.fModelNumber) << "</modelNumber>" << endl;
192 }
193 if (dd.fModelURL) {
194 tmp << " <modelURL>" << QuoteForXML (dd.fModelURL->As<String> ()) << "</modelURL>" << endl;
195 }
196 if (dd.fSerialNumber) {
197 tmp << " <serialNumber>" << QuoteForXML (dd.fSerialNumber) << "</serialNumber>" << endl;
198 }
199 tmp << " <UDN>" << QuoteForXML (dd.fUDN) << "</UDN>" << endl;
200 if (dd.fUPC) {
201 tmp << " <UPC>" << QuoteForXML (*dd.fUPC) << "</UPC>" << endl;
202 }
203 if (dd.fIcons) {
204 tmp << " <iconList>" << endl;
205 for (const DeviceDescription::Icon& i : *dd.fIcons) {
206 tmp << " <icon>" << endl;
207 tmp << " <mimetype>" << QuoteForXML (i.fMimeType.As<String> ()) << "</mimetype>" << endl;
208 tmp << " <width>" << i.fHorizontalPixels << "</width>" << endl;
209 tmp << " <height>" << i.fVerticalPixels << "</height>" << endl;
210 tmp << " <depth>" << i.fColorDepth << "</depth>" << endl;
211 tmp << " <url>" << QuoteForXML (i.fURL.As<String> ()) << "</url>" << endl;
212 tmp << " </icon>" << endl;
213 }
214 tmp << " </iconList>" << endl;
215 }
216 if (dd.fServices) {
217 tmp << " <serviceList>" << endl;
218 for (const DeviceDescription::Service& i : *dd.fServices) {
219 tmp << " <service>" << endl;
220 tmp << " <serviceType>" << QuoteForXML (i.fServiceType) << "</serviceType>" << endl;
221 tmp << " <serviceId>" << QuoteForXML (i.fServiceID) << "</serviceId>" << endl;
222 tmp << " <SCPDURL>" << QuoteForXML (i.fSCPDURL.As<String> ()) << "</SCPDURL>" << endl;
223 tmp << " <controlURL>" << QuoteForXML (i.fControlURL.As<String> ()) << "</controlURL>" << endl;
224 tmp << " <eventSubURL>" << QuoteForXML (i.fEventSubURL.As<String> ()) << "</eventSubURL>" << endl;
225 tmp << " </service>" << endl;
226 }
227 tmp << " </serviceList>" << endl;
228 }
229
230#if 0
231 tmp << " <deviceList>" << endl;
232 // <!-- Description of embedded devices defined by a UPnP Forum working committee
233 // (if any) go here -->
234 // <!-- Description of embedded devices added by UPnP vendor (if any) go here -->
235 tmp << " </deviceList>" << endl;
236#endif
237
238 if (dd.fPresentationURL.has_value ()) {
239 tmp << " <presentationURL>" << QuoteForXML (dd.fPresentationURL->As<String> ()) << "</presentationURL>" << endl;
240 }
241 tmp << " </device>" << endl;
242 tmp << "</root>" << endl;
243 return Streams::iostream::InputStreamFromStdIStream::New<byte> (tmp).ReadAll ();
244}
245
246/*
247 ********************************************************************************
248 ******************************* UPnP::DeSerialize ******************************
249 ********************************************************************************
250 */
251DeviceDescription UPnP::DeSerialize (const Memory::BLOB& b)
252{
253 using namespace Stroika::Foundation::DataExchange;
254 using namespace Stroika::Foundation::DataExchange::StructuredStreamEvents;
255 using namespace Stroika::Foundation::DataExchange::XML;
256
257 static const ObjectReader::Registry kTypesRegistry_ = [] () {
258 ObjectReader::Registry registry;
259 registry.AddCommonType<String> ();
260 registry.AddCommonType<optional<String>> ();
261 registry.AddCommonType<uint16_t> ();
262 registry.AddCommonType<URI> ();
263 registry.AddCommonType<optional<URI>> ();
264 registry.AddCommonReader_Simple<InternetMediaType> ([] (const String& s) { return InternetMediaType{s}; });
266 {Name{"mimetype"sv}, &DeviceDescription::Icon::fMimeType},
267 {Name{"width"sv}, &DeviceDescription::Icon::fHorizontalPixels},
268 {Name{"height"sv}, &DeviceDescription::Icon::fVerticalPixels},
269 {Name{"depth"sv}, &DeviceDescription::Icon::fColorDepth},
270 {Name{"url"sv}, &DeviceDescription::Icon::fURL},
271 });
272 registry.AddCommonReader_Class<DeviceDescription::Service> ({
273 {Name{"serviceType"sv}, &DeviceDescription::Service::fServiceType},
274 {Name{"serviceId"sv}, &DeviceDescription::Service::fServiceID},
275 {Name{"SCPDURL"sv}, &DeviceDescription::Service::fSCPDURL},
276 {Name{"controlURL"sv}, &DeviceDescription::Service::fControlURL},
277 });
279 registry.AddCommonType<optional<Collection<DeviceDescription::Icon>>> ();
281 registry.AddCommonType<optional<Collection<DeviceDescription::Service>>> ();
283 {Name{"presentationURL"sv}, &DeviceDescription::fPresentationURL},
284 {Name{"deviceType"sv}, &DeviceDescription::fDeviceType},
285 {Name{"manufacturer"sv}, &DeviceDescription::fManufactureName},
286 {Name{"friendlyName"sv}, &DeviceDescription::fFriendlyName},
287 {Name{"manufacturerURL"sv}, &DeviceDescription::fManufacturingURL},
288 {Name{"modelDescription"sv}, &DeviceDescription::fModelDescription},
289 {Name{"modelName"sv}, &DeviceDescription::fModelName},
290 {Name{"modelNumber"sv}, &DeviceDescription::fModelNumber},
291 {Name{"modelURL"sv}, &DeviceDescription::fModelURL},
292 {Name{"serialNum"sv}, &DeviceDescription::fSerialNumber},
293 {Name{"UDN"sv}, &DeviceDescription::fUDN},
294 {Name{"UPC"sv}, &DeviceDescription::fUPC},
295 {Name{"iconList"sv}, &DeviceDescription::fIcons},
296 {Name{"serviceList"sv}, &DeviceDescription::fServices},
297 });
298 return registry;
299 }();
300
301 DeviceDescription deviceDescription;
302#if USE_NOISY_TRACE_IN_THIS_MODULE_
303 DbgTrace (L"xml data: %s", Streams::BinaryToText::Reader::New (b).ReadAll ().c_str ());
304#endif
305#if qStroika_Foundation_DataExchange_XML_SupportParsing
306 {
308 kTypesRegistry_, MakeSharedPtr<ObjectReader::ReadDownToReader> (kTypesRegistry_.MakeContextReader (&deviceDescription), Name{"device"sv})};
309 XML::SAXParse (b, &ctx);
310 }
311#else
312 WeakAssertNotImplemented (); // may want to allow to continue, as this may not be critical functionality, but you probably want XML parser when running this code...
313#endif
314#if USE_NOISY_TRACE_IN_THIS_MODULE_
315 DbgTrace ("deviceDescription: {}"_f, deviceDescription);
316#endif
317 return deviceDescription;
318}
#define WeakAssertNotImplemented()
Definition Assertions.h:483
#define DbgTrace
Definition Trace.h:309
Similar to String, but intended to more efficiently construct a String. Mutable type (String is large...
String is like std::u32string, except it is much easier to use, often much more space efficient,...
Definition String.h:201
A Collection<T> is a container to manage an un-ordered collection of items, without equality defined ...
ObjectVariantMapper can be used to map C++ types to and from variant-union types, which can be transp...
nonvirtual void AddClass(const Traversal::Iterable< StructFieldInfo > &fieldDescriptions, const ClassMapperOptions< CLASS > &mapperOptions={})
nonvirtual void AddCommonType(ARGS &&... args)
nonvirtual void AddCommonReader_Class(const Traversal::Iterable< StructFieldInfo > &fieldDescriptions)
nonvirtual void AddCommonReader_Simple(const function< T(String)> &converterFromString2T)
Add reader for any type that is stringish: provide convert function from string to T; Simple wrapper ...
nonvirtual shared_ptr< IElementConsumer > MakeContextReader(type_index ti, void *destinationObject) const
Ptr New(const InputStream::Ptr< byte > &src, optional< AutomaticCodeCvtFlags > codeCvtFlags={}, optional< SeekableFlag > seekable={}, ReadAhead readAhead=eReadAheadAllowed)
Create an InputStream::Ptr<Character> from the arguments (usually binary source) - which can be used ...