blob: b33cf13a4447ae7e4b554d632a803a47d9c53ce1 [file] [log] [blame]
// Copyright 2019 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef LIBIPP_IPP_PACKAGE_H_
#define LIBIPP_IPP_PACKAGE_H_
#include "ipp_attribute.h"
#include "ipp_enums.h"
#include "ipp_export.h"
#include <cstdint>
#include <map>
#include <string>
#include <vector>
namespace ipp {
class Group;
// This class represents IPP frame. It is container for Groups that represent
// IPP attributes groups (like operation-attributes). Groups in a single Package
// must have unique tags (names).
class IPP_EXPORT Package {
public:
// destructor
virtual ~Package();
// Returns vector of all groups in the package, all pointers are != nullptr.
// Returned vector = GetKnownGroups() + vector with unknown groups.
std::vector<Group*> GetAllGroups();
std::vector<const Group*> GetAllGroups() const;
// Returns pointer to the group with given tag.
// Returns nullptr if there is no group with given tag in the package.
Group* GetGroup(GroupTag);
const Group* GetGroup(GroupTag) const;
// Adds a new group to the package and returns pointer to it or nullptr if
// a group with given tag already exists in the package.
Group* AddUnknownGroup(GroupTag, bool is_a_set);
// Returns reference to payload (e.g. document to print), empty vector means
// no payload.
std::vector<uint8_t>& Data() { return data_; }
const std::vector<uint8_t>& Data() const { return data_; }
protected:
Package() = default;
private:
// Copy/move/assign constructors/operators are not available.
Package(const Package&) = delete;
Package(Package&&) = delete;
Package& operator=(const Package&) = delete;
Package& operator=(Package&&) = delete;
// Returns vector with groups in the schema, all pointers are != nullptr.
// This method must be overloaded in derived classes with schema.
virtual std::vector<Group*> GetKnownGroups() { return {}; }
virtual std::vector<const Group*> GetKnownGroups() const { return {}; }
std::vector<Group*> unknown_groups_;
std::vector<uint8_t> data_;
};
// Defined later in this file.
class Collection;
// Base class represents single IPP attribute group or a sequence of the
// same IPP attribute groups. Single instance of IPP attribute groups is
// represented by Collection object.
class IPP_EXPORT Group {
public:
virtual ~Group() { Resize(0); }
// Returns tag of the group.
GroupTag GetName() const { return name_; }
// Returns true if it is a sequence of IPP groups (Collections) or false
// if it is a single IPP group (one Collection).
bool IsASet() const { return is_a_set_; }
// Returns the current number of elements (IPP groups) in the Group.
// (IsASet() == false) => always returns 1.
size_t GetSize() const { return groups_.size(); }
// Resizes a sequence of IPP groups.
// Does nothing if (IsASet() == false) and (|new_size| > 0).
void Resize(size_t new_size) {
if (!is_a_set_ && new_size > 1)
return;
while (new_size < groups_.size()) {
delete groups_.back();
groups_.pop_back();
}
while (new_size > groups_.size()) {
groups_.push_back(CreateCollection());
}
}
// Returns a pointer to underlying collection, representing one of the IPP
// groups. Returns nullptr <=> (index >= GetSize()).
Collection* GetCollection(size_t index = 0) {
if (index >= groups_.size())
return nullptr;
return groups_[index];
}
const Collection* GetCollection(size_t index = 0) const {
if (index >= groups_.size())
return nullptr;
return groups_.at(index);
}
protected:
Group(GroupTag name, bool is_a_set) : name_(name), is_a_set_(is_a_set) {}
private:
virtual Collection* CreateCollection() = 0;
GroupTag name_;
bool is_a_set_;
std::vector<Collection*> groups_;
};
// Final class for Groups, represents Group with single IPP attribute group
// defined in the schema. Template parameter TCollection must be a class
// derived from Collection and defines the structure of the group.
template <class TCollection>
class SingleGroup : public Group {
public:
explicit SingleGroup(GroupTag name) : Group(name, false) {}
// Allows to refer to fields in the underlying collection.
// Creates the collection if it not exists.
TCollection* operator->() {
Resize(1);
return dynamic_cast<TCollection*>(GetCollection());
}
// Returns reference to the underlying collection. If the group is empty
// (GetSize() == 0) returns a reference to an empty static collection.
const TCollection& Get() const {
const Collection* coll = GetCollection();
if (coll == nullptr)
return TCollection::empty;
return *(dynamic_cast<const TCollection*>(coll));
}
private:
Collection* CreateCollection() override { return new TCollection; }
};
// Final class for Group, represents sequence of IPP attribute groups with
// the same tag and defined in the schema. Template parameter TCollection is
// a class derived from Collection and defines the structure of a single group.
template <class TCollection>
class SetOfGroups : public Group {
public:
explicit SetOfGroups(GroupTag name) : Group(name, true) {}
// If |index| is out of range, the vector is resized to (index+1).
TCollection& operator[](size_t index) {
if (GetSize() <= index)
Resize(index + 1);
return *(dynamic_cast<TCollection*>(GetCollection(index)));
}
// Const version of the method above. If |index| is out of range,
// a reference to an empty static collection is returned.
const TCollection& At(size_t index) const {
const Collection* coll = GetCollection(index);
if (coll == nullptr)
return TCollection::empty;
return *(dynamic_cast<const TCollection*>(coll));
}
private:
Collection* CreateCollection() override { return new TCollection; }
};
// Final class for Group, represents Group not defined in the schema.
class UnknownGroup : public Group {
public:
UnknownGroup(GroupTag name, bool is_a_set) : Group(name, is_a_set) {}
private:
Collection* CreateCollection() override { return new EmptyCollection; }
};
} // namespace ipp
#endif // LIBIPP_IPP_PACKAGE_H_