Stroika Library 3.0d25
 
Loading...
Searching...
No Matches
Variant/FormURLEncoded/Reader.cpp
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2026. 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"
14
15#include "Reader.h"
16
17using namespace Stroika::Foundation;
18using namespace Stroika::Foundation::Common;
20using namespace Stroika::Foundation::DataExchange::Variant;
21using namespace Stroika::Foundation::DataExchange::Variant::FormURLEncoded;
22using namespace Stroika::Foundation::Streams;
23
27using Containers::Set;
28using Memory::MakeSharedPtr;
30
31// Comment this in to turn on aggressive noisy DbgTrace in this module
32//#define USE_NOISY_TRACE_IN_THIS_MODULE_ 1
33/*
34 ********************************************************************************
35 ****************** DataExchange::::FormURLEncoded::Reader **********************
36 ********************************************************************************
37 */
38class FormURLEncoded::Reader::Rep_ final : public Variant::Reader::_IRep, public Memory::UseBlockAllocationIfAppropriate<Rep_> {
39public:
40 Rep_ () = default;
41 virtual optional<filesystem::path> GetDefaultFileSuffix () const override
42 {
43 return nullopt;
44 }
45 virtual VariantValue Read (const InputStream::Ptr<byte>& in) const override
46 {
47 return VariantValue{ReadAssociation (in).Map<Mapping<String, VariantValue>> (
48 [] (auto i) { return KeyValuePair<String, VariantValue>{i.fKey, VariantValue{i.fValue}}; })};
49 }
50 virtual VariantValue Read (const InputStream::Ptr<Character>& in) const override
51 {
52 // Treat a string as mapped to UTF-8 and interpret that, not sure if thats they best thing todo - maybe disallow/throw?
53 return Read (Streams::TextToBinary::Reader::New (in));
54 }
55 nonvirtual Association<String, String> ReadAssociation (const InputStream::Ptr<byte>& in) const
56 {
57#if USE_NOISY_TRACE_IN_THIS_MODULE_
58 Debug::TraceContextBumper ctx{"DataExchange::Variant::FormURLEncoded::Reader::Rep_::ReadMatrix"};
59#endif
61 Streams::StreamReader<byte> streamReader{in};
62 auto toString = [] (span<byte> bytes) {
63 // https://url.spec.whatwg.org/#application/x-www-form-urlencoded says map '+' to space, but thats not part of URL-encode apparently
64 for (auto&& c : bytes) {
65 if (c == static_cast<byte> ('+')) {
66 c = static_cast<byte> (' ');
67 }
68 }
69 u8string asU8Str{reinterpret_cast<const char8_t*> (bytes.data ()), bytes.size ()};
70 return IO::Network::UniformResourceIdentification::PCTDecode2String (asU8Str);
71 };
72 while (not streamReader.IsAtEOF ()) {
74 span<byte> line = streamReader.ReadBlocking (&lineBuf, static_cast<byte> ('&'));
75 if (not line.empty ()) {
76 if (auto eqSign = find (line.begin (), line.end (), static_cast<byte> ('=')); eqSign != line.end ()) {
77 // add a=b
78 result.Add (toString (line.subspan (0, eqSign - line.begin ())), toString (line.subspan (eqSign + 1 - line.begin ())));
79 }
80 else {
81 // add a=
82 result.Add (toString (line), String{});
83 }
84 }
85 }
86 return result;
87 }
88};
89FormURLEncoded::Reader::Reader ()
90 : inherited{MakeSharedPtr<Rep_> ()}
91{
92}
93
95{
96 return Debug::UncheckedDynamicCast<const Rep_&> (_ConstGetRep ()).ReadAssociation (in);
97}
auto MakeSharedPtr(ARGS_TYPE &&... args) -> shared_ptr< T >
same as make_shared, but if type T has block allocation, then use block allocation for the 'shared pa...
conditional_t< qStroika_Foundation_Memory_PreferBlockAllocation and andTrueCheck, BlockAllocationUseHelper< T >, Common::Empty > UseBlockAllocationIfAppropriate
Use this to enable block allocation for a particular class. Beware of subclassing.
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 Mapping uniquely associates two elements: a key and a value (use Assocation to allow multiple value...
A generalization of a vector: a container whose elements are keyed by the natural numbers.
Set<T> is a container of T, where once an item is added, additionally adds () do nothing.
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:234
StreamReader is an non-essential Stream utility, adding simplicity of use for a common use case,...