1 // Copyright 2019 The Chromium OS Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef LIBIPP_IPP_ATTRIBUTE_H_ 6 #define LIBIPP_IPP_ATTRIBUTE_H_ 7 8 #include <cstdint> 9 #include <memory> 10 #include <string> 11 #include <vector> 12 13 #include "ipp_enums.h" // NOLINT(build/include) 14 #include "ipp_export.h" // NOLINT(build/include) 15 16 namespace ipp { 17 18 // Represents the current state of the attribute: 19 // set/unset or one of the out-of-band values. 20 // "unset" means that the attribute is not included in a IPP frame. 21 enum class AttrState : uint8_t { 22 unset = 0x00, // internal 23 set = 0x01, // internal 24 unsupported = 0x10, // [rfc8010] 25 unknown = 0x12, // [rfc8010] 26 novalue_ = 0x13, // [rfc8010] 27 not_settable = 0x15, // [rfc3380] 28 delete_attribute = 0x16, // [rfc3380] 29 admin_define = 0x17 // [rfc3380] 30 }; 31 32 // Represents types of values hold by attributes (see [rfc8010]). 33 // "collection" means that the attribute has class Collection as a value. 34 enum class AttrType : uint8_t { 35 integer = 0x21, 36 boolean = 0x22, 37 enum_ = 0x23, 38 octetString = 0x30, 39 dateTime = 0x31, 40 resolution = 0x32, 41 rangeOfInteger = 0x33, 42 collection = 0x34, // use begCollection tag value [rfc8010] 43 text = 0x35, // use textWithLanguage tag value [rfc8010] 44 name = 0x36, // use nameWithLanguage tag value [rfc8010] 45 keyword = 0x44, 46 uri = 0x45, 47 uriScheme = 0x46, 48 charset = 0x47, 49 naturalLanguage = 0x48, 50 mimeMediaType = 0x49 51 }; 52 53 // It is used to hold name and text values (see [rfc8010]). 54 // If language == "" it represents nameWithoutLanguage or textWithoutLanguage, 55 // otherwise it represents nameWithLanguage or textWithLanguage. 56 struct StringWithLanguage { 57 std::string value = ""; 58 std::string language = ""; 59 StringWithLanguage() = default; StringWithLanguageStringWithLanguage60 StringWithLanguage(const std::string& value, const std::string& language) 61 : value(value), language(language) {} StringWithLanguageStringWithLanguage62 explicit StringWithLanguage(const std::string& value) : value(value) {} StringWithLanguageStringWithLanguage63 explicit StringWithLanguage(std::string&& value) : value(value) {} stringStringWithLanguage64 operator std::string() const { return value; } 65 }; 66 67 // Represents resolution type from [rfc8010]. 68 struct Resolution { 69 int size1 = 0; 70 int size2 = 0; 71 enum Units { kDotsPerInch = 3, kDotsPerCentimeter = 4 } units = kDotsPerInch; 72 Resolution() = default; 73 Resolution(int size1, int size2, Units units = Units::kDotsPerInch) size1Resolution74 : size1(size1), size2(size2), units(units) {} 75 }; 76 77 // Represents rangeOfInteger type from [rfc8010]. 78 struct RangeOfInteger { 79 int min_value = 0; 80 int max_value = 0; 81 RangeOfInteger() = default; RangeOfIntegerRangeOfInteger82 RangeOfInteger(int min_value, int max_value) 83 : min_value(min_value), max_value(max_value) {} 84 }; 85 86 // Represents dateTime type from [rfc8010,rfc2579]. 87 struct DateTime { 88 uint16_t year = 2000; 89 uint8_t month = 1; // 1..12 90 uint8_t day = 1; // 1..31 91 uint8_t hour = 0; // 0..23 92 uint8_t minutes = 0; // 0..59 93 uint8_t seconds = 0; // 0..60 (60 - leap second :-) 94 uint8_t deci_seconds = 0; // 0..9 95 uint8_t UTC_direction = '+'; // '+' / '-' 96 uint8_t UTC_hours = 0; // 0..13 97 uint8_t UTC_minutes = 0; // 0..59 98 }; 99 100 // Functions converting basic types to string. For enums it returns empty 101 // string if given value is not defined. 102 IPP_EXPORT std::string ToString(AttrState value); 103 IPP_EXPORT std::string ToString(AttrType value); 104 IPP_EXPORT std::string ToString(bool value); 105 IPP_EXPORT std::string ToString(int value); 106 IPP_EXPORT std::string ToString(const Resolution& value); 107 IPP_EXPORT std::string ToString(const RangeOfInteger& value); 108 IPP_EXPORT std::string ToString(const DateTime& value); 109 110 // Functions extracting basic types from string. 111 // Returns false <=> given pointer is nullptr or given string does not 112 // represent a correct value. 113 IPP_EXPORT bool FromString(const std::string& str, bool* value); 114 IPP_EXPORT bool FromString(const std::string& str, int* value); 115 116 // It is defined in ipp_package.h. Represents struct-like entity with 117 // attributes, where each attribute must have unique name. 118 class Collection; 119 120 // Base class representing Attribute, contains general API for Attribute. 121 class IPP_EXPORT Attribute { 122 public: 123 virtual ~Attribute() = default; 124 125 // Returns a type of the attribute. GetType()126 AttrType GetType() const { return type_; } 127 128 // Returns a state of an attribute. Default state is always AttrState::unset, 129 // setting any value with SetValues(...) switches the state to AttrState::set. 130 // State can be also set by hand with SetState() method. 131 // If (GetType() != collection): returns a state value saved in the object. 132 // If (GetType() == collection): the following algorithm is used: 133 // 1. If the attribute's state was set directly to one of out-of-band values 134 // (values different that AttrState::unset and AttrState::set), this value 135 // is returned. 136 // 2. If (GetState() == unset) for all members in all Collections in the 137 // attribute, the value AttrState::unset is returned (recursive check). 138 // 3. Returns AttrState::set. 139 AttrState GetState(); 140 141 // Sets state of the attribute. 142 // If (GetType() != collection): it sets directly the state in the object. 143 // If (GetType() == collection): the following rules apply: 144 // * If (new_state == unset), it clears out-of-band value from the object 145 // and calls recursively SetState(unset) for all members in all 146 // Collections in the attribute. 147 // * If (new_state == set), it only clears out-of-band value from the object. 148 // * In all other cases it just sets directly the given out-of-band value in 149 // the object. 150 void SetState(AttrState new_state); 151 152 // Returns true if the attribute is a set, false if it is a single value. IsASet()153 bool IsASet() const { return is_a_set_; } 154 155 // Returns enum value corresponding to attributes name. If the name has 156 // no corresponding AttrName value, it returns AttrName::_unknown. GetNameAsEnum()157 AttrName GetNameAsEnum() const { return name_; } 158 159 // Returns an attribute's name as a non-empty string. GetName()160 virtual std::string GetName() const { return ToString(name_); } 161 162 // Returns the current number of elements (values or Collections). 163 // (IsASet() == false) => always returns 1. 164 virtual size_t GetSize() const = 0; 165 166 // Resizes a set of values or Collections if IsASet() == true. 167 // (IsASet() == false) => does nothing. 168 virtual void Resize(size_t) = 0; 169 170 // Retrieves a value from an attribute, returns true for success and 171 // false if the index is out of range or the value cannot be converted 172 // to given variable (in this case, the given variable is not modified). 173 // (val == nullptr) => does nothing and returns false. 174 // (GetType() == collection) => does nothing and returns false. 175 virtual bool GetValue(std::string* val, size_t index = 0) const { 176 return false; 177 } 178 virtual bool GetValue(StringWithLanguage* val, size_t index = 0) const { 179 return false; 180 } 181 virtual bool GetValue(int* val, size_t index = 0) const { return false; } 182 virtual bool GetValue(Resolution* val, size_t index = 0) const { 183 return false; 184 } 185 virtual bool GetValue(RangeOfInteger* val, size_t index = 0) const { 186 return false; 187 } 188 virtual bool GetValue(DateTime* val, size_t index = 0) const { return false; } 189 190 // Stores a value in given attribute's element. If the attribute is a set 191 // and given index is out of range, the underlying container is resized. 192 // Returns true for success and false if given value cannot be converted 193 // to internal variable or one of the following rules applies: 194 // (GetType() == collection) => does nothing and returns false. 195 // (IsASet() == false && index != 0) => does nothing and returns false. 196 virtual bool SetValue(const std::string& val, size_t index = 0) { 197 return false; 198 } 199 virtual bool SetValue(const StringWithLanguage& val, size_t index = 0) { 200 return false; 201 } 202 virtual bool SetValue(const int& val, size_t index = 0) { return false; } 203 virtual bool SetValue(const Resolution& val, size_t index = 0) { 204 return false; 205 } 206 virtual bool SetValue(const RangeOfInteger& val, size_t index = 0) { 207 return false; 208 } 209 virtual bool SetValue(const DateTime& val, size_t index = 0) { return false; } 210 211 // Returns a pointer to Collection. 212 // (GetType() != collection || index >= GetSize()) <=> returns nullptr. 213 virtual Collection* GetCollection(size_t index = 0) { return nullptr; } 214 215 protected: 216 // Constructor is available from derived classes only. Attribute(AttrName name,bool is_a_set,AttrType type)217 Attribute(AttrName name, bool is_a_set, AttrType type) 218 : type_(type), name_(name), is_a_set_(is_a_set) {} 219 220 const AttrType type_; 221 const AttrName name_; 222 const bool is_a_set_; 223 AttrState state_ = AttrState::unset; 224 225 private: 226 // Copy/move/assign constructors/operators are forbidden. 227 Attribute(const Attribute&) = delete; 228 Attribute(Attribute&&) = delete; 229 Attribute& operator=(const Attribute&) = delete; 230 Attribute& operator=(Attribute&&) = delete; 231 }; 232 233 // Basic values are stored in attributes as variables of the following types: 234 enum InternalType : uint8_t { 235 kInteger, // int 236 kString, // std::string 237 kStringWithLanguage, // ipp::StringWithLanguage 238 kResolution, // ipp::Resolution 239 kRange, // ipp::RangeOfIntegers 240 kDateTime // ipp::DateTime 241 }; 242 243 // General class for storing basic values, provides implementation for methods 244 // GetValue(...) and SetValue(...). It is not suppose to be used directly. 245 class IPP_EXPORT ValueAttribute : public Attribute { 246 public: 247 virtual ~ValueAttribute(); 248 249 // Implementation of general API from Attribute. 250 size_t GetSize() const override; 251 void Resize(size_t) override; 252 bool GetValue(std::string* val, size_t index = 0) const override; 253 bool GetValue(StringWithLanguage* val, size_t index = 0) const override; 254 bool GetValue(int* val, size_t index = 0) const override; 255 bool GetValue(Resolution* val, size_t index = 0) const override; 256 bool GetValue(RangeOfInteger* val, size_t index = 0) const override; 257 bool GetValue(DateTime* val, size_t index = 0) const override; 258 bool SetValue(const std::string& val, size_t index = 0) override; 259 bool SetValue(const StringWithLanguage& val, size_t index = 0) override; 260 bool SetValue(const int& val, size_t index = 0) override; 261 bool SetValue(const Resolution& val, size_t index = 0) override; 262 bool SetValue(const RangeOfInteger& val, size_t index = 0) override; 263 bool SetValue(const DateTime& val, size_t index = 0) override; 264 265 protected: 266 // Constructor is available from derived classes only. 267 ValueAttribute(AttrName, bool is_a_set, AttrType, InternalType); 268 269 private: 270 InternalType cpp_type_; 271 union Data { 272 std::vector<int> as_int; 273 std::vector<std::string> as_string; 274 std::vector<Resolution> as_resolution; 275 std::vector<RangeOfInteger> as_ranges; 276 std::vector<DateTime> as_datetime; 277 std::vector<StringWithLanguage> as_string_with_language; 278 // We have to provide constructor and destructor because union's 279 // elements are not trivial. The union is initialized/deleted in 280 // constructor/destructor of the class. Data()281 IPP_PRIVATE Data() {} ~Data()282 IPP_PRIVATE ~Data() {} 283 } data_; 284 }; 285 286 // These templates convert the type from specialized API to the internal type 287 // used to store values. Default is integer because it is used for all enum 288 // types. 289 template <typename TType> 290 struct AsInternalType { 291 static const InternalType value = InternalType::kInteger; 292 typedef int Type; 293 }; 294 template <> 295 struct AsInternalType<std::string> { 296 static const InternalType value = InternalType::kString; 297 typedef std::string Type; 298 }; 299 template <> 300 struct AsInternalType<Resolution> { 301 static const InternalType value = InternalType::kResolution; 302 typedef Resolution Type; 303 }; 304 template <> 305 struct AsInternalType<RangeOfInteger> { 306 static const InternalType value = InternalType::kRange; 307 typedef RangeOfInteger Type; 308 }; 309 template <> 310 struct AsInternalType<DateTime> { 311 static const InternalType value = InternalType::kDateTime; 312 typedef DateTime Type; 313 }; 314 template <> 315 struct AsInternalType<StringWithLanguage> { 316 static const InternalType value = InternalType::kStringWithLanguage; 317 typedef StringWithLanguage Type; 318 }; 319 320 // Final class for Attribute, represents single value from the schema. 321 // Template parameter defines type of the value. 322 template <typename TValue> 323 class SingleValue : public ValueAttribute { 324 public: 325 SingleValue(AttrName name, AttrType type) 326 : ValueAttribute(name, false, type, AsInternalType<TValue>::value) {} 327 328 // Specialized API 329 void Set(const TValue& val) { 330 SetValue(static_cast<typename AsInternalType<TValue>::Type>(val)); 331 } 332 TValue Get() const { 333 typename AsInternalType<TValue>::Type val; 334 GetValue(&val); 335 return static_cast<TValue>(val); 336 } 337 }; 338 339 // Specialization of the template above for StringWithLanguage to add 340 // Set(std::string). 341 template <> 342 class SingleValue<StringWithLanguage> : public ValueAttribute { 343 public: 344 SingleValue(AttrName name, AttrType type) 345 : ValueAttribute( 346 name, false, type, AsInternalType<StringWithLanguage>::value) {} 347 348 // Specialized API 349 void Set(const StringWithLanguage& val) { 350 SetValue(static_cast<StringWithLanguage>(val)); 351 } 352 void Set(const std::string& val) { 353 SetValue(static_cast<StringWithLanguage>(val)); 354 } 355 StringWithLanguage Get() const { 356 StringWithLanguage val; 357 GetValue(&val); 358 return val; 359 } 360 }; 361 362 // Final class for Attribute, represents sets of values. 363 // Template parameter defines type of a single value. 364 template <typename TValue> 365 class SetOfValues : public ValueAttribute { 366 public: 367 SetOfValues(AttrName name, AttrType type) 368 : ValueAttribute(name, true, type, AsInternalType<TValue>::value) {} 369 370 // Specialized API 371 void Set(const std::vector<TValue>& vals) { 372 Resize(vals.size()); 373 for (size_t i = 0; i < vals.size(); ++i) 374 SetValue(vals[i], i); 375 } 376 std::vector<TValue> Get() const { 377 std::vector<TValue> vals(GetSize()); 378 for (size_t i = 0; i < vals.size(); ++i) { 379 typename AsInternalType<TValue>::Type val; 380 GetValue(&val, i); 381 vals[i] = static_cast<TValue>(val); 382 } 383 return vals; 384 } 385 void Add(const std::vector<TValue>& vals) { 386 const size_t old_size = GetSize(); 387 Resize(old_size + vals.size()); 388 for (size_t i = 0; i < vals.size(); ++i) 389 SetValue(vals[i], old_size + i); 390 } 391 }; 392 393 // Specialization of the template above for StringWithLanguage to add 394 // Set/Add(std::string). 395 template <> 396 class SetOfValues<StringWithLanguage> : public ValueAttribute { 397 public: 398 SetOfValues(AttrName name, AttrType type) 399 : ValueAttribute( 400 name, true, type, AsInternalType<StringWithLanguage>::value) {} 401 402 // Specialized API 403 void Set(const std::vector<StringWithLanguage>& vals) { 404 Resize(vals.size()); 405 for (size_t i = 0; i < vals.size(); ++i) 406 SetValue(vals[i], i); 407 } 408 void Set(const std::vector<std::string>& vals) { 409 Resize(vals.size()); 410 for (size_t i = 0; i < vals.size(); ++i) 411 SetValue(vals[i], i); 412 } 413 std::vector<StringWithLanguage> Get() const { 414 std::vector<StringWithLanguage> vals(GetSize()); 415 for (size_t i = 0; i < vals.size(); ++i) { 416 StringWithLanguage val; 417 GetValue(&val, i); 418 vals[i] = val; 419 } 420 return vals; 421 } 422 void Add(const std::vector<StringWithLanguage>& vals) { 423 const size_t old_size = GetSize(); 424 Resize(old_size + vals.size()); 425 for (size_t i = 0; i < vals.size(); ++i) 426 SetValue(vals[i], old_size + i); 427 } 428 void Add(const std::vector<std::string>& vals) { 429 const size_t old_size = GetSize(); 430 Resize(old_size + vals.size()); 431 for (size_t i = 0; i < vals.size(); ++i) 432 SetValue(vals[i], old_size + i); 433 } 434 }; 435 436 // Final class for Attribute, represents sets of values that can contain names 437 // outside the schema. 438 template <typename TValue> 439 class OpenSetOfValues : public ValueAttribute { 440 public: 441 OpenSetOfValues(AttrName name, AttrType type) 442 : ValueAttribute(name, true, type, InternalType::kString) {} 443 444 // Specialized API 445 void Set(const std::vector<std::string>& vals) { 446 Resize(vals.size()); 447 for (size_t i = 0; i < vals.size(); ++i) 448 SetValue(vals[i], i); 449 } 450 void Set(const std::vector<TValue>& vals) { 451 Resize(vals.size()); 452 for (size_t i = 0; i < vals.size(); ++i) 453 SetValue(ToString(vals[i]), i); 454 } 455 std::vector<std::string> Get() const { 456 std::vector<std::string> vals(GetSize()); 457 for (size_t i = 0; i < vals.size(); ++i) 458 GetValue(&(vals[i]), i); 459 return vals; 460 } 461 void Add(const std::vector<std::string>& vals) { 462 const size_t old_size = GetSize(); 463 Resize(old_size + vals.size()); 464 for (size_t i = 0; i < vals.size(); ++i) 465 SetValue(vals[i], old_size + i); 466 } 467 void Add(const std::vector<TValue>& vals) { 468 const size_t old_size = GetSize(); 469 Resize(old_size + vals.size()); 470 for (size_t i = 0; i < vals.size(); ++i) 471 SetValue(ToString(vals[i]), old_size + i); 472 } 473 }; 474 475 // Final class for Attribute, represents attribute not defined in the schema. 476 class IPP_EXPORT UnknownValueAttribute : public ValueAttribute { 477 public: 478 UnknownValueAttribute(const std::string& name, bool is_a_set, AttrType type); 479 std::string GetName() const override { return str_name_; } 480 481 private: 482 std::string str_name_; 483 }; 484 485 // Final class for Attribute, represents single IPP collection. 486 // Template parameter is a class derived from Collection and defines 487 // the structure. 488 template <class TCollection> 489 class SingleCollection : public Attribute, public TCollection { 490 public: 491 explicit SingleCollection(AttrName name) 492 : Attribute(name, false, AttrType::collection) {} 493 494 // Implementation of general API from Attribute. 495 size_t GetSize() const override { return 1; } 496 void Resize(size_t) override {} 497 Collection* GetCollection(size_t index = 0) override { 498 if (index == 0) 499 return this; 500 return nullptr; 501 } 502 }; 503 504 // Final class for Attribute, represents set of collections from IPP spec. 505 // Template parameter is a class derived from Collection and defines 506 // the structure of a single collection. 507 template <class TCollection> 508 class SetOfCollections : public Attribute { 509 public: 510 explicit SetOfCollections(AttrName name) 511 : Attribute(name, true, AttrType::collection) {} 512 513 // Implementation of general API from Attribute. 514 size_t GetSize() const override { return collections_.size(); } 515 void Resize(size_t new_size) override { 516 while (collections_.size() < new_size) 517 collections_.push_back(std::make_unique<TCollection>()); 518 collections_.resize(new_size); 519 } 520 Collection* GetCollection(size_t index = 0) override { 521 if (index >= collections_.size()) 522 return nullptr; 523 return collections_[index].get(); 524 } 525 526 // Specialized API 527 // If index is out of range, the vector is resized to (index+1). 528 TCollection& operator[](size_t index) { 529 if (index >= collections_.size()) 530 Resize(index + 1); 531 return *(collections_[index]); 532 } 533 534 private: 535 std::vector<std::unique_ptr<TCollection>> collections_; 536 }; 537 538 class IPP_EXPORT UnknownCollectionAttribute : public Attribute { 539 public: 540 UnknownCollectionAttribute(const std::string& name, bool is_a_set); 541 542 // Implementation of general API from Attribute. 543 std::string GetName() const override { return str_name_; } 544 size_t GetSize() const override { return collections_.size(); } 545 void Resize(size_t new_size) override; 546 Collection* GetCollection(size_t index = 0) override { 547 if (index >= collections_.size()) 548 return nullptr; 549 return collections_[index].get(); 550 } 551 552 private: 553 std::string str_name_; 554 std::vector<std::unique_ptr<Collection>> collections_; 555 }; 556 557 } // namespace ipp 558 559 #endif // LIBIPP_IPP_ATTRIBUTE_H_ 560