Accept scientific notation in the KiCad file parser

Even though we no longer write the scientific notation to the file, we
used to and should support reading it for backwards compatibility.
This commit is contained in:
Ian McInerney
2026-02-25 15:55:00 +00:00
parent b42b6a4c62
commit 934a5bac34
3 changed files with 129 additions and 1 deletions
+3 -1
View File
@@ -858,6 +858,8 @@ wxArrayString* DSNLEXER::ReadCommentLines()
return ret;
}
// Skip the white space and also accept both normal numbers and scientfic notation
#define FROM_CHARS_FLAGS ( fast_float::chars_format::skip_white_space | fast_float::chars_format::general )
double DSNLEXER::parseDouble()
{
@@ -867,7 +869,7 @@ double DSNLEXER::parseDouble()
double dval{};
fast_float::from_chars_result res = fast_float::from_chars( str.data(), str.data() + str.size(), dval,
fast_float::chars_format::skip_white_space );
FROM_CHARS_FLAGS );
if( res.ec != std::errc() )
{
@@ -0,0 +1,99 @@
(kicad_pcb
(version 20260206)
(generator "pcbnew")
(generator_version "10.0")
(general
(thickness 1.6)
(legacy_teardrops no)
)
(paper "A4")
(layers
(0 "F.Cu" signal)
(2 "B.Cu" signal)
(9 "F.Adhes" user "F.Adhesive")
(11 "B.Adhes" user "B.Adhesive")
(13 "F.Paste" user)
(15 "B.Paste" user)
(5 "F.SilkS" user "F.Silkscreen")
(7 "B.SilkS" user "B.Silkscreen")
(1 "F.Mask" user)
(3 "B.Mask" user)
(17 "Dwgs.User" user "User.Drawings")
(19 "Cmts.User" user "User.Comments")
(21 "Eco1.User" user "User.Eco1")
(23 "Eco2.User" user "User.Eco2")
(25 "Edge.Cuts" user)
(27 "Margin" user)
(31 "F.CrtYd" user "F.Courtyard")
(29 "B.CrtYd" user "B.Courtyard")
(35 "F.Fab" user)
(33 "B.Fab" user)
(39 "User.1" user)
(41 "User.2" user)
(43 "User.3" user)
(45 "User.4" user)
)
(setup
(pad_to_mask_clearance 0)
(allow_soldermask_bridges_in_footprints no)
(tenting
(front yes)
(back yes)
)
(covering
(front no)
(back no)
)
(plugging
(front no)
(back no)
)
(capping no)
(filling no)
(pcbplotparams
(layerselection 0x00000000_00000000_55555555_5755f5ff)
(plot_on_all_layers_selection 0x00000000_00000000_00000000_00000000)
(disableapertmacros no)
(usegerberextensions no)
(usegerberattributes yes)
(usegerberadvancedattributes yes)
(creategerberjobfile yes)
(dashed_line_dash_ratio 12)
(dashed_line_gap_ratio 3)
(svgprecision 4)
(plotframeref no)
(mode 1)
(useauxorigin no)
(pdf_front_fp_property_popups yes)
(pdf_back_fp_property_popups yes)
(pdf_metadata yes)
(pdf_single_document no)
(dxfpolygonmode yes)
(dxfimperialunits yes)
(dxfusepcbnewfont yes)
(psnegative no)
(psa4output no)
(plot_black_and_white yes)
(sketchpadsonfab no)
(plotpadnumbers no)
(hidednponfab no)
(sketchdnponfab yes)
(crossoutdnponfab yes)
(subtractmaskfromsilk no)
(outputformat 1)
(mirror no)
(drillshape 1)
(scaleselection 1)
(outputdirectory "")
)
)
(embedded_fonts no)
(gr_arc
(start -1.23 -1.469694)
(mid 4.17 -4.5e-05)
(end -1.229954 1.469772)
(stroke (width 0.1) (type solid))
(layer "F.Fab")
(uuid "ce1fc66d-8f6f-47a2-834f-aebcff9deee4")
)
)
@@ -31,6 +31,7 @@
#include <pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.h>
#include <board.h>
#include <pcb_shape.h>
#include <zone.h>
@@ -128,4 +129,30 @@ BOOST_AUTO_TEST_CASE( Issue23125_EmptyZoneDiscarded )
}
/**
* Verify the parser still can read floating point values written in scientific notation.
* Even though the KiCad file writter doesn't write using scientific notation anymore, at one
* point it did, so the parser must still support reading it.
*/
BOOST_AUTO_TEST_CASE( ScientificNotationLoading )
{
std::string dataPath = KI_TEST::GetPcbnewTestDataDir()
+ "plugins/kicad_sexpr/";
std::unique_ptr<BOARD> testBoard = std::make_unique<BOARD>();
kicadPlugin.LoadBoard( dataPath + "ScientificNotation.kicad_pcb", testBoard.get() );
// The file contains 1 arc with scientific notation in its coordinates
BOOST_CHECK_EQUAL( testBoard->Drawings().size(), 1 );
PCB_SHAPE* arc = dynamic_cast<PCB_SHAPE*>( testBoard->Drawings().front() );
// The arc's midpoint should be located at (4.17, -4.5e-05) in file units
BOOST_REQUIRE( arc );
BOOST_TEST( arc->GetArcMid().x == 4170000 );
BOOST_TEST( arc->GetArcMid().y == -45 );
}
BOOST_AUTO_TEST_SUITE_END()