Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
Variant/FormURLEncoded/Reader.cpp
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#include "Stroika/Foundation/StroikaPreComp.h"
5
6#include "Stroika/Foundation/Characters/FloatConversion.h"
8#include "Stroika/Foundation/Characters/String2Int.h"
9#include "Stroika/Foundation/DataExchange/BadFormatException.h"
13
14#include "Reader.h"
15
16using namespace Stroika::Foundation;
17using namespace Stroika::Foundation::Common;
19using namespace Stroika::Foundation::DataExchange::Variant;
20using namespace Stroika::Foundation::DataExchange::Variant::FormURLEncoded;
21using namespace Stroika::Foundation::Streams;
22
26using Containers::Set;
28
29// Comment this in to turn on aggressive noisy DbgTrace in this module
30//#define USE_NOISY_TRACE_IN_THIS_MODULE_ 1
31/*
32 ********************************************************************************
33 ****************** DataExchange::::FormURLEncoded::Reader **********************
34 ********************************************************************************
35 */
36class FormURLEncoded::Reader::Rep_ : public Variant::Reader::_IRep {
37public:
38 Rep_ ()
39 {
40 }
41 virtual _SharedPtrIRep Clone () const override
42 {
43 return make_shared<Rep_> ();
44 }
45 virtual optional<filesystem::path> GetDefaultFileSuffix () const override
46 {
47 return nullopt;
48 }
49 virtual VariantValue Read (const InputStream::Ptr<byte>& in) override
50 {
51 return VariantValue{ReadAssociation (in).Map<Mapping<String, VariantValue>> (
52 [] (auto i) { return KeyValuePair<String, VariantValue>{i.fKey, VariantValue{i.fValue}}; })};
53 }
54 virtual VariantValue Read (const InputStream::Ptr<Character>& in) override
55 {
56 // Treat a string as mapped to UTF-8 and interpret that, not sure if thats they best thing todo - maybe disallow/throw?
57 return Read (Streams::TextToBinary::Reader::New (in));
58 }
59 nonvirtual Association<String, String> ReadAssociation (const InputStream::Ptr<byte>& in) const
60 {
61#if USE_NOISY_TRACE_IN_THIS_MODULE_
62 Debug::TraceContextBumper ctx{"DataExchange::Variant::FormURLEncoded::Reader::Rep_::ReadMatrix"};
63#endif
65 Streams::StreamReader<byte> streamReader{in};
66 auto toString = [] (span<byte> bytes) {
67 // https://url.spec.whatwg.org/#application/x-www-form-urlencoded says map '+' to space, but thats not part of URL-encode apparently
68 for (auto&& c : bytes) {
69 if (c == static_cast<byte> ('+')) {
70 c = static_cast<byte> (' ');
71 }
72 }
73 u8string asU8Str{reinterpret_cast<const char8_t*> (bytes.data ()), bytes.size ()};
74 return IO::Network::UniformResourceIdentification::PCTDecode2String (asU8Str);
75 };
76 while (not streamReader.IsAtEOF ()) {
78 span<byte> line = streamReader.ReadBlocking (&lineBuf, static_cast<byte> ('&'));
79 if (not line.empty ()) {
80 if (auto eqSign = find (line.begin (), line.end (), static_cast<byte> ('=')); eqSign != line.end ()) {
81 // add a=b
82 result.Add (toString (line.subspan (0, eqSign - line.begin ())), toString (line.subspan (eqSign + 1 - line.begin ())));
83 }
84 else {
85 // add a=
86 result.Add (toString (line), String{});
87 }
88 }
89 }
90 return result;
91 }
92};
93FormURLEncoded::Reader::Reader ()
94 : inherited{make_shared<Rep_> ()}
95{
96}
97
99{
100 return Debug::UncheckedDynamicCast<const Rep_&> (_GetRep ()).ReadAssociation (in);
101}
String is like std::u32string, except it is much easier to use, often much more space efficient,...
Definition String.h:201
An Association pairs key values with (possibly multiple or none) mapped_type values....
nonvirtual void Add(ArgByValueType< key_type > key, ArgByValueType< mapped_type > newElt)
A generalization of a vector: a container whose elements are keyed by the natural numbers.
Definition Sequence.h:187
Set<T> is a container of T, where once an item is added, additionally adds () do nothing.
Definition Set.h:105
nonvirtual Association< String, String > ReadAssociation(const Streams::InputStream::Ptr< byte > &in) const
Simple variant-value (case variant union) object, with (variant) basic types analogous to a value in ...
Logically halfway between std::array and std::vector; Smart 'direct memory array' - which when needed...
InputStream<>::Ptr is Smart pointer (with abstract Rep) class defining the interface to reading from ...
Iterable<T> is a base class for containers which easily produce an Iterator<T> to traverse them.
Definition Iterable.h:237
StreamReader is an non-essential Stream utility, adding simplicity of use for a common use case,...