I am currently working on the DOT format exporter in igraph, and I am trying to uderstand why a certain hack is present in the codebase.
igraph only supports generic numerical attributes, but does not distinguish between integer and floating point types. The DOT writer currently has code that attempts to write integral values as integers, i.e. write
123 instead of
According to the DOT format spec, at the highest level all values in the DOT language are just strings. It is not clear at what point they are interpreted as specific types such as
Question 1: If an attribute that is specified as needing to be
int is given in a floating point format, is that a problem for Graphviz? Can you please show an example of when and how it becomes a problem?
Question 2: Is it fine to unconditionally quote all floating point numerical values when writing DOT files? Graphviz cannot parse values such as
1.23e4 without quotes, so unconditional quoting would be a simple way to get around this.
Thanks in advance for any advice on this topic.
Thanks for the links to the code, this makes it quite clear that
1e3 would not be interpreted as the integer
1000. I’ll make sure that igraph is well-behaved when writing integral values in DOT files.
I was not around at the time it was written, but I presume parsing was more expensive or humans were expected to read the output. Nowadays I doubt printing
42 instead of
42.000 makes much of a difference.
According to my reading of the source code, if one uses
42.0 in a place where an
int is expected, parsing should fail, and the default value should be substituted automatically.
It looks like
strtol(), which would parse
42 and stop at the
late_int() does verify that the whole string was parsed by
strtol(), and if not, it seems to return a default value,
if (p == endp || rv > INT_MAX)
return defaultValue; /* invalid int format */
I’m actually having some trouble verifying this empirically, as I am not yet fluent with GraphViz. Could someone help with this?
(That said, we now do make sure to always print integral values as
10000000 and not
10000000.00 in igraph.)
Sorry, I misread the preceding chain and thought we were talking about generalized backends like e.g. SVG, not specifically the DOT backend.
I would assume none of it is well specified. That is, the DOT format spec does not precisely match what the code does and empirically what the code does is what matters. We’ve had a variant of this problem before when people have implemented third party DOT parsers based on the spec and then discovered they disagree with Graphviz’ parser.
I would suggest you take one of two approaches:
- Mimic exactly what Graphviz’ DOT exporter is doing.
- Print attributes differently based on type, as determined from the attribute documentation.
I would guess (1) is simpler as it doesn’t require you to update your exporter whenever new Graphviz attributes are added. Though admittedly this is very rare. Depending on your license and/or implementation language, you may be able to copy-paste the exporter code with minor edits.