1 // Copyright 2019 The Amber Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "src/descriptor_set_and_binding_parser.h"
16
17 #include <cctype>
18 #include <iostream>
19 #include <limits>
20
21 #include "src/tokenizer.h"
22
23 namespace amber {
24
25 DescriptorSetAndBindingParser::DescriptorSetAndBindingParser() = default;
26
27 DescriptorSetAndBindingParser::~DescriptorSetAndBindingParser() = default;
28
Parse(const std::string & buffer_id)29 Result DescriptorSetAndBindingParser::Parse(const std::string& buffer_id) {
30 size_t idx = 0;
31
32 // Pipeline name
33 if (!std::isdigit(buffer_id[idx]) && std::isalpha(buffer_id[idx]) &&
34 buffer_id[idx] != ':' && buffer_id[idx] != '-') {
35 idx++;
36 while (idx < buffer_id.size() && buffer_id[idx] != ':')
37 idx++;
38
39 pipeline_name_ = buffer_id.substr(0, idx);
40
41 // Move past the :
42 idx += 1;
43 }
44 if (idx >= buffer_id.size())
45 return Result("Invalid buffer id: " + buffer_id);
46
47 Tokenizer t(buffer_id.substr(idx));
48 auto token = t.NextToken();
49 if (token->IsInteger()) {
50 if (token->AsInt32() < 0) {
51 return Result(
52 "Descriptor set and binding for a buffer must be non-negative "
53 "integer, but you gave: " +
54 token->ToOriginalString());
55 }
56
57 uint32_t val = token->AsUint32();
58 token = t.NextToken();
59 if (token->IsEOS() || token->IsEOL()) {
60 descriptor_set_ = 0;
61 binding_ = val;
62 return {};
63 }
64
65 descriptor_set_ = val;
66 }
67
68 if (!token->IsIdentifier())
69 return Result("Invalid buffer id: " + buffer_id);
70
71 auto& str = token->AsString();
72 if (str.size() < 2 || str[0] != ':')
73 return Result("Invalid buffer id: " + buffer_id);
74
75 auto substr = str.substr(1, str.size());
76 // Validate all characters are integers.
77 for (size_t i = 0; i < substr.size(); ++i) {
78 if (substr[i] < '0' || substr[i] > '9') {
79 return Result(
80 "Binding for a buffer must be non-negative integer, "
81 "but you gave: " +
82 substr);
83 }
84 }
85
86 uint64_t binding_val = strtoul(substr.c_str(), nullptr, 10);
87 if (binding_val > std::numeric_limits<uint32_t>::max())
88 return Result("binding value too large in probe ssbo command: " +
89 token->ToOriginalString());
90 if (static_cast<int32_t>(binding_val) < 0) {
91 return Result(
92 "Binding for a buffer must be non-negative integer, but you gave: " +
93 token->ToOriginalString());
94 }
95
96 binding_ = static_cast<uint32_t>(binding_val);
97 return {};
98 }
99
100 } // namespace amber
101