// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROMEOS_PRINTING_URI_IMPL_H_
#define CHROMEOS_PRINTING_URI_IMPL_H_
#include <string>
#include <utility>
#include <vector>
#include "chromeos/printing/uri.h"
// This file contains a declaration of struct used in the implementation of
// class Uri declared in uri.h. This file is not supposed to be included
// anywhere outside of the class Uri.
namespace chromeos {
using Iter = std::string::const_iterator;
class Uri::Pim {
public:
Pim();
Pim(const Pim&);
~Pim();
// These methods parse and normalize the corresponding component(s) from the
// input string |begin|-|end|. Each component is saved only if successfully
// parsed and verified. In case of an error, the field |parser_error| is set
// and false is returned. All methods assume that |begin| <= |end|.
// Additional notes for particular components:
// * Scheme: if the current Port is unspecified and the new Scheme has
// default port number, the Port is set to this default value
// * Authority: this is Userinfo + Host + Port, see description in uri.h for
// the grammar
// * Port: an empty string means -1, see the method SavePort(int) below
// * Path: the input string must be empty or starts from '/'
bool ParseScheme(const Iter& begin, const Iter& end);
bool ParseAuthority(const Iter& begin, const Iter& end);
bool ParsePort(const Iter& begin, const Iter& end);
bool ParsePath(const Iter& begin, const Iter& end);
bool ParseQuery(const Iter& begin, const Iter& end);
bool ParseFragment(const Iter& begin, const Iter& end);
// This method parse the whole URI. It calls internally the methods
// Parse*(...) declared above. In case of an error, the method set the field
// |parser_error| and returns false. Parsing stops on the first error,
// components that have been successfully parsed are saved.
bool ParseUri(const Iter& begin, const Iter end);
// This method fails (and return false) <=> |port| is smaller than -1 or
// larger than 65535. If |port| == -1 and the current Scheme has a default
// port, the default port is set as a new Port number. The field
// |parser_error| is set accordingly.
bool SavePort(int port);
// These methods save values of corresponding components. The template
// parameter |encoded| trigger resolution of %-escaped characters. If set to
// true, every % sign in the input value is treated as the beginning of
// %-escaped character; if set to false, % signs are treated as regular ASCII
// characters. All input values are validated and normalized, but without
// %-escaping fragile characters (components are stored in "native" form). In
// case of a failure, false is returned, the value of target component is not
// modified, and the field |parser_error| is set accordingly.
template <bool encoded>
bool SaveUserinfo(const std::string& val);
template <bool encoded>
bool SaveHost(const std::string& val);
template <bool encoded>
bool SavePath(const std::vector<std::string>& val);
template <bool encoded>
bool SaveQuery(const std::vector<std::pair<std::string, std::string>>& val);
template <bool encoded>
bool SaveFragment(const std::string& val);
// Getters for all fields.
const std::string& scheme() const { return scheme_; }
const std::string& userinfo() const { return userinfo_; }
const std::string& host() const { return host_; }
int port() const { return port_; }
const std::vector<std::string>& path() const { return path_; }
const std::vector<std::pair<std::string, std::string>>& query() const {
return query_;
}
const std::string& fragment() const { return fragment_; }
// Access to the |parser_error_|
ParserError& parser_error() { return parser_error_; }
private:
// Reads the string |begin|-|end| and perform the following operations:
// 1. if |plus_to_space| is true, all '+' signs are converted to ' ' (space)
// 2. if |encoded| is true, all % signs are treated as initiators of
// %-escaped characters and decoded to corresponding ASCII
// 3. if |case_insensitive| is true, all capital ASCII letters are converted
// to lowercase
// 4. all UTF-8 characters are validated
// 5. all ASCII characters are validated (see the section Encoding in uri.h)
// The output is saved to |out|. In case of an error, the method set the field
// |parser_error| and returns false.
// The following initial requirements must be met:
// * |begin| <= |end|
// * |out| must point to an empty string
// When the method returns false, |out| may contain invalid value.
template <bool encoded, bool case_insensitive = false>
bool ParseString(const Iter& begin,
const Iter& end,
std::string* out,
bool plus_to_space = false);
// Components values. They are valid and normalized, but before %-escaping.
std::string scheme_;
std::string userinfo_;
std::string host_;
int port_ = -1; // -1 means "unspecified"
// A list of path's segments, without separators ('/').
std::vector<std::string> path_;
// A list of parameters name=value; value may be empty.
std::vector<std::pair<std::string, std::string>> query_;
std::string fragment_;
// The last parser status.
ParserError parser_error_;
};
} // namespace chromeos
#endif // CHROMEOS_PRINTING_URI_IMPL_H_