cgv
Loading...
Searching...
No Matches
component_format.cxx
1#include "component_format.h"
2#include <iostream>
3#include <cgv/utils/tokenizer.h>
4#include <cgv/utils/scan.h>
5#include <cgv/type/info/type_name.h>
6#include <cgv/type/info/type_id.h>
7
8using namespace cgv::utils;
9using namespace cgv::type::info;
10
11namespace cgv {
12 namespace data {
13
14static const char* component_formats[] = {
15 "",
16 "R",
17 "G",
18 "B",
19 "A",
20 "L",
21 "I",
22 "L,A",
23 "I,A",
24 "R,G",
25 "R,G,B",
26 "R,G,B,A",
27 "B,G,R",
28 "B,G,R,A",
29 "D",
30 "S",
31 "px,py",
32 "px,py,pz",
33 "px,py,pz,pw",
34 "nx,ny",
35 "nx,ny,nz",
36 "ts,tt",
37 "ts,tt,tr",
38 "ts,tt,tr,tq",
39};
40
43{
44// component_string += ',';
45 component_positions.clear();
46 if (component_string.empty())
47 return;
48 component_positions.push_back(0);
49 for (unsigned int i=0; i<component_string.size(); ++i) {
50 if (component_string[i] == ',' || component_string[i] == ';') {
51// component_string[i] = 0;
52 if (i+1 < component_string.size())
53 component_positions.push_back(i+1);
54 }
55 }
56}
57
59void component_format::set_components(const std::string& _components)
60{
61 component_string = _components;
63}
64
66component_format::component_format(TypeId _type_id, const std::string& _components,
67 unsigned align, unsigned d0, unsigned d1, unsigned d2, unsigned d3)
68 : packing_info(align, d0,d1,d2,d3), component_type(_type_id), component_string(_components)
69{
70 component_interpretation = CII_DEFAULT;
72}
73
76 unsigned align, unsigned d0, unsigned d1, unsigned d2, unsigned d3)
77 : packing_info(align, d0,d1,d2,d3), component_type(_type_id),
78 component_string(component_formats[cf])
79{
80 component_interpretation = CII_DEFAULT;
82}
83
85component_format::component_format(const std::string& description)
86{
87 set_component_format(description);
89}
90
91bool extract_special_type(const std::string& tok, TypeId& component_type, ComponentIntegerInterpretation& cii)
92{
93 if (tok.empty())
94 return false;
95 ComponentIntegerInterpretation ci = CII_DEFAULT;
96 if (tok[0] == '_')
97 ci = CII_INTEGER;
98 else if (tok[0] == 's')
99 ci = CII_SNORM;
100 else
101 return false;
102 if (tok.size() == 1) {
103 component_type = TI_UNDEF;
104 cii = ci;
105 return true;
106 }
107 if (tok.size() <= 4)
108 return false;
109 unsigned offset = 1;
110 bool is_signed = true;
111 if (ci == CII_INTEGER && tok[1] == 'u') {
112 is_signed = false;
113 offset = 2;
114 }
115 if (tok[offset] != 'i')
116 return false;
117 if (tok[offset + 1] != 'n')
118 return false;
119 if (tok[offset + 2] != 't')
120 return false;
121 unsigned bits = 8;
122 if (!((tok.size() == offset + 4) && (tok[offset + 3] == '8'))) {
123 if (tok.size() != offset + 5)
124 return false;
125 switch (tok[offset + 3]) {
126 case '1':
127 bits = 16;
128 if (tok[offset + 4] != '6')
129 return false;
130 break;
131 case '3':
132 bits = 32;
133 if (tok[offset + 4] != '2')
134 return false;
135 break;
136 case '6':
137 bits = 64;
138 if (tok[offset + 4] != '4')
139 return false;
140 break;
141 default:
142 return false;
143 }
144 }
145 cii = ci;
146 if (is_signed) {
147 switch (bits) {
148 case 8: component_type = cgv::type::info::TI_INT8; break;
149 case 16: component_type = cgv::type::info::TI_INT16; break;
150 case 32: component_type = cgv::type::info::TI_INT32; break;
151 case 64: component_type = cgv::type::info::TI_INT64; break;
152 }
153 }
154 else {
155 switch (bits) {
156 case 8: component_type = cgv::type::info::TI_UINT8; break;
157 case 16: component_type = cgv::type::info::TI_UINT16; break;
158 case 32: component_type = cgv::type::info::TI_UINT32; break;
159 case 64: component_type = cgv::type::info::TI_UINT64; break;
160 }
161 }
162 return true;
163}
164
166bool component_format::set_component_format(const std::string& description)
167{
168 if (description.empty()) {
169 }
170 last_error = "";
171 set_packing(false);
172 std::vector<token> toks;
173 tokenizer(description).set_sep("[]:|,").bite_all(toks);
174 if (toks.size() == 0) {
175 last_error = "no tokens found that would define a component format";
176 return false;
177 }
178 unsigned int i=1;
179 component_interpretation = CII_DEFAULT;
180 if (to_string(toks[0]) == "[" || to_string(toks[0]) == ":" ||
181 to_string(toks[0]) == "|") {
182 component_type = TI_UNDEF;
183 i = 0;
184 }
185 else if (to_string(toks[0]) == "undef")
186 component_type = TI_UNDEF;
187 else {
188 if (extract_special_type(to_string(toks[0]), component_type, component_interpretation)) {}
189 else {
191 if (component_type == TI_UNDEF) {
192 last_error = to_string(toks[0]) + " ... unknown type name";
193 return false;
194 }
195 }
196 }
197 if (toks.size() == i) {
198 last_error = "description incomplete after <type_name>";
199 return false;
200 }
201 if (toks[i] == ":") {
202 if (toks.size() == ++i) {
203 last_error = "description incomplete after <type_name:>";
204 return false;
205 }
206 int bit_depth;
207 if (is_integer(to_string(toks[i]), bit_depth)) {
208 for (int ci=0; ci<4; ++ci)
209 set_bit_depth(ci,bit_depth);
210 set_packing(true);
211 ++i;
212 }
213 else {
214 last_error = "expected integer token after <type_name:>";
215 return false;
216 }
217 }
218 if (toks[i] == "|") {
219 if (toks.size() == ++i) {
220 last_error = "description incomplete after <type_name|>";
221 return false;
222 }
223 int align;
224 if (is_integer(to_string(toks[i]), align)) {
226 ++i;
227 }
228 else {
229 last_error = "expected integer token after <type_name|>";
230 return false;
231 }
232 }
233 if (toks.size() == i) {
234 last_error = "description incomplete after <type_name>";
235 return false;
236 }
237 int ci = 0;
238 if (toks[i] != "[") {
239 last_error = "expected <[> after type_name";
240 return false;
241 }
242 if (toks.size() == ++i) {
243 last_error = "description incomplete after <[>";
244 return false;
245 }
246 component_string = "";
247 while (toks[i] != "]") {
248 if (component_string.size() > 0)
249 component_string += ',';
250 component_string += to_string(toks[i]);
251 if (toks.size() == ++i) {
252 last_error = "description incomplete after <[ or ,>";
253 return false;
254 }
255 if (toks[i] == ":") {
256 if (toks.size() == ++i) {
257 last_error = "description incomplete after <component_name:>";
258 return false;
259 }
260 int bit_depth;
261 if (is_integer(to_string(toks[i]), bit_depth)) {
262 if (ci < 4)
263 set_bit_depth(ci,bit_depth);
264 set_packing(true);
265 if (toks.size() == ++i) {
266 last_error = "description incomplete after <component_name:bit_depth>";
267 return false;
268 }
269 }
270 else {
271 last_error = "expected integer token after <component_name:>";
272 return false;
273 }
274 }
275 if (toks[i] == ",") {
276 if (toks.size() == ++i) {
277 last_error = "description incomplete after <,>";
278 return false;
279 }
280 }
281 ++ci;
282 }
284 return true;
285}
286
291
297
299
302{
303 return last_error;
304}
305
308{
309 component_type = TI_UNDEF;
310 component_string.clear();
311 component_positions.clear();
313}
314
317{
318 return component_type == TI_UNDEF;
319}
320
323{
324 return (unsigned int) component_positions.size();
325}
326
328unsigned int component_format::get_component_index(const std::string& name) const
329{
330 for (unsigned int i=0; i<get_nr_components(); ++i) {
331 if (name == get_component_name(i))
332 return i;
333 }
334 return -1;
335}
336
337
339std::string component_format::get_component_name(unsigned int i) const
340{
341 if (i >= get_nr_components())
342 return "";
343 unsigned n = (unsigned)component_string.size();
344 if (i+1 < get_nr_components())
345 n = component_positions[i+1]-1;
346 n -= component_positions[i];
347 return component_string.substr(component_positions[i],n);
348}
349
352{
353 std::string component_name_list;
354 for (unsigned int i=0; i<get_nr_components(); ++i) {
355 if (!component_name_list.empty())
356 component_name_list += ',';
357 component_name_list += get_component_name(i);
358 }
359 for (ComponentFormat cf = ComponentFormat(CF_UNDEF+1); cf < CF_LAST; cf = ComponentFormat(cf+1)) {
360 if (component_name_list == component_formats[cf])
361 return cf;
362 }
363 return CF_UNDEF;
364}
365
367void component_format::set_component_names(const std::string& _component_name_list)
368{
369 component_string = _component_name_list;
371}
372
375{
376 component_string = component_formats[_cf];
378}
379
385
388{
389 component_type = _type_id;
390}
392{
393 if (is_packing()) {
394 unsigned nr_bits = 0;
395 for (unsigned ci = 0; ci < get_nr_components(); ++ci)
396 nr_bits += unsigned(align(get_bit_depth(ci), get_component_alignment()));
397 return unsigned(align(nr_bits, 8)/8);
398 }
400}
402{
403 return *this;
404}
406{
407 *static_cast<packing_info*>(this) = pi;
408}
410{
412 return false;
414 return false;
416 return false;
417 for (unsigned int i=0; i<get_nr_components(); ++i) {
418 if (std::string(get_component_name(i)) != cf.get_component_name(i))
419 return false;
420 }
421 return true;
422}
424{
425 return !(*this == cf);
426}
427std::ostream& operator << (std::ostream& os, const component_format& cf)
428{
429 switch (cf.get_integer_interpretation()) {
430 case CII_SNORM: os << 's'; break;
431 case CII_INTEGER: os << '_'; break;
432 default: break;
433 }
434 if (cf.get_component_type() != TI_UNDEF)
436 bool individual_bit_depth = false;
437 if (cf.is_packing()) {
438 if (cf.get_bit_depth(0) == cf.get_bit_depth(1) &&
439 cf.get_bit_depth(0) == cf.get_bit_depth(2) &&
440 cf.get_bit_depth(0) == cf.get_bit_depth(3))
441 os << ':' << cf.get_bit_depth(0);
442 else
443 individual_bit_depth = true;
444 }
445 if (cf.get_component_alignment() != 1)
446 os << '|' << cf.get_component_alignment();
447 os << "[";
448 for (unsigned int i=0; i<cf.get_nr_components(); ++i) {
449 if (i > 0)
450 os << ',';
451 os << cf.get_component_name(i);
452 if (individual_bit_depth)
453 os << ':' << cf.get_bit_depth(i);
454 }
455 os << ']';
456 return os;
457}
459 const component_format& fmt1,
460 const component_format& fmt2)
461{
462 // check standard component format equality first
464 if (cf != CF_UNDEF) {
467 if ((cf1 == cf) != (cf2 == cf))
468 return cf1 == cf;
469 }
470 // check number components equality
471 unsigned int nc = fmt.get_nr_components();
472 unsigned int nc1 = fmt1.get_nr_components();
473 unsigned int nc2 = fmt2.get_nr_components();
474 if ((nc1 == nc) != (nc2 == nc))
475 return nc1 == nc;
476 if ((nc1 >= nc) != (nc2 >= nc))
477 return nc1 >= nc;
478
479 // check type equality
480 TypeId ti = fmt.get_component_type();
481 TypeId ti1 = fmt1.get_component_type();
482 TypeId ti2 = fmt2.get_component_type();
483 if ((ti1 == ti) != (ti2 == ti))
484 return ti1 == ti;
485
486 // check integer interpretation equality
490 if ((cii1 == cii) != (cii2 == cii))
491 return cii1 == cii;
492
493 // check whether to pack equality
494 bool ip = fmt.is_packing();
495 bool ip1 = fmt1.is_packing();
496 bool ip2 = fmt2.is_packing();
497 if ((ip1 == ip) != (ip2 == ip))
498 return ip1 == ip;
499
500 // check component bit equality
501 unsigned int diff1 = 0;
502 unsigned int diff2 = 0;
503 for (unsigned int i=0; i<nc; ++i) {
504 unsigned int bd = get_type_size(fmt.get_component_type())*8;
505 if (ip)
506 bd = fmt.get_bit_depth(i);
507 if (i >= nc1)
508 diff1 += bd;
509 else {
510 unsigned int bd1 = get_type_size(fmt1.get_component_type())*8;
511 if (ip1)
512 bd1 = fmt1.get_bit_depth(i);
513 if (bd1 > bd)
514 diff1 += bd1-bd;
515 else
516 diff1 += 2*(bd-bd1);
517 }
518 if (i >= nc2)
519 diff2 += bd;
520 else {
521 unsigned int bd2 = get_type_size(fmt2.get_component_type())*8;
522 if (ip2)
523 bd2 = fmt2.get_bit_depth(i);
524 if (bd2 > bd)
525 diff2 += bd2-bd;
526 else
527 diff2 += 2*(bd-bd2);
528 }
529 }
530 if (diff1 != diff2)
531 return diff1 < diff2;
532
533 return true;
534}
535
537 const component_format& fmt,
538 const char** format_descriptions,
539 const component_format* fmt0,
540 bool (*fmt1_better_match)(
541 const component_format& fmt,
542 const component_format& fmt1,
543 const component_format& fmt2))
544{
545 component_format best_match;
546 unsigned int best_i = -1;
547 unsigned int i = 0;
548 if (fmt0)
549 best_match = *fmt0;
550 else {
551 best_match = component_format(*format_descriptions);
552 best_i = 0;
553 ++format_descriptions;
554 ++i;
555 }
556 while (*format_descriptions) {
557 component_format fmt1(*format_descriptions);
558 if (!fmt1_better_match(fmt, best_match, fmt1)) {
559 best_match = fmt1;
560 best_i = i;
561 }
562 ++format_descriptions;
563 ++i;
564 }
565 return best_i;
566}
567
568
569 }
570}
the component format inherits the information of a packing_info and adds information on the component...
bool operator!=(const component_format &cf) const
comparison between component formats
std::string component_string
store all component names in one string separated with 0-chars
std::string get_component_name(unsigned int i) const
return the name of the component with index i
bool set_component_format(const std::string &description)
set component format from description string, which has the following syntax.
component_format(const std::string &description)
construct from description string, see set_component_format for docu
cgv::type::info::TypeId component_type
store the type id of the component type
void clear()
clear the component format
static std::string last_error
store the last error that appeared during parsing of a description
void set_component_type(cgv::type::info::TypeId _type_id)
set the component type
const packing_info & get_packing_info() const
return the packing info by simple conversion of the this pointer
unsigned int get_component_index(const std::string &name) const
return the index of a component given by name or -1 if not found
void set_integer_interpretation(ComponentIntegerInterpretation cii)
set the integer interpretation
void extract_components()
extract components from component string
ComponentIntegerInterpretation get_integer_interpretation() const
return current integer interpretation
void set_packing_info(const packing_info &pi)
set packing info by simply assigning to a converted this pointer
void set_components(const std::string &_components)
comma separated list of component descriptors, for example "R,G,B"
cgv::type::info::TypeId get_component_type() const
return the component type
ComponentFormat get_standard_component_format() const
return whether the component format is one of the standard formats
static const std::string & get_last_error()
returns an error string after parsing of description string has failed
std::vector< unsigned short > component_positions
store the position of each component in the component string
void set_component_names(const std::string &_component_name_list)
set component names from a comma or colon separated list of names
unsigned int get_entry_size() const
return the size of one entry of components in bytes
bool operator==(const component_format &cf) const
comparison between component formats
ComponentIntegerInterpretation component_interpretation
interpretation of integer typed components
bool empty() const
return whether the component format is defined
unsigned int get_nr_components() const
return the number of components
the packing_info class stores information about packed integers structures.
static size_t align(size_t v, unsigned a)
return the next integer larger or equal to v which is dividable by a
bool is_packing() const
return whether packing is enabled
void set_bit_depth(unsigned ci, unsigned depth)
set the bit depth of the ci-th component
unsigned get_bit_depth(unsigned ci) const
return the bit depth of the ci-th component
unsigned int get_component_alignment() const
return the component alignment in bits in the packed case and in bytes in the unpacked case
void set_packing(bool enable=true)
set the packing flag
void set_component_alignment(unsigned a)
set the component alignment in bits in the packed case and in bytes in the unpacked case
void clear()
clear packing info information
the tokenizer allows to split text into tokens in a convenient way.
Definition tokenizer.h:68
tokenizer & set_sep(const std::string &sep, bool merge)
set the list of separators and specify whether succeeding separators are merged into single tokens
Definition tokenizer.cxx:59
ComponentFormat
define standard formats, which should be used to avoid wrong assignment of component names
@ CF_LAST
texture coordinats format with components ts, tt, tr and tq
std::ostream & operator<<(std::ostream &os, const component_format &cf)
stream out operator writes the component format in the syntax of description strings as defined in th...
unsigned find_best_match(const component_format &fmt, const char **format_descriptions, const component_format *fmt0, bool(*fmt1_better_match)(const component_format &fmt, const component_format &fmt1, const component_format &fmt2))
find the best matching format in a list of formats described by strings and return index of best matc...
ComponentIntegerInterpretation
define different interpretations of integer components
bool fmt1_compares_better(const component_format &fmt, const component_format &fmt1, const component_format &fmt2)
default function to check whether fmt1 is a better match to fmt than fmt2
namespace for templates that provide type information
Definition type_access.h:9
TypeId get_type_id(const std::string &_type_name)
function that returns the type id of a type name
Definition type_id.cxx:53
unsigned int get_type_size(TypeId tid)
function that returns the size of a type specified through TypeId
Definition type_id.cxx:18
const char * get_type_name(TypeId tid)
function that returns the name of a type specified through TypeId
Definition type_id.cxx:117
TypeId
ids for the different types and type constructs
Definition type_id.h:12
@ TI_INT16
signed integer stored in 8 bits
Definition type_id.h:20
@ TI_INT8
boolean
Definition type_id.h:19
@ TI_INT32
signed integer stored in 16 bits
Definition type_id.h:21
@ TI_UINT32
unsigned integer stored in 16 bits
Definition type_id.h:25
@ TI_UINT8
signed integer stored in 64 bits
Definition type_id.h:23
@ TI_INT64
signed integer stored in 32 bits
Definition type_id.h:22
@ TI_UINT16
unsigned integer stored in 8 bits
Definition type_id.h:24
@ TI_UINT64
unsigned integer stored in 32 bits
Definition type_id.h:26
namespace that holds tools that dont fit any other namespace
std::string to_string(const std::string &v, unsigned int w, unsigned int p, bool)
specialization of conversion from string to strings
bool is_integer(const char *begin, const char *end, int &value)
check if the text range (begin,end( defines an integer value. If yes, store the value in the passed r...
Definition scan.cxx:367
the cgv namespace
Definition print.h:11
Helper functions to process strings.