kicad/common/io/altium/altium_props_utils.cpp

153 lines
4.8 KiB
C++

/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2019-2020 Thomas Pointhuber <thomas.pointhuber@gmx.at>
* Copyright (C) 2020-2024 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "altium_props_utils.h"
#include <limits>
#include <sstream>
#include <math/util.h>
#include <wx/crt.h>
#include <wx/log.h>
#include <wx/translation.h>
int32_t ALTIUM_PROPS_UTILS::ConvertToKicadUnit( const double aValue )
{
constexpr double int_limit = ( std::numeric_limits<int>::max() - 10 ) / 2.54;
int32_t iu = KiROUND( Clamp<double>( -int_limit, aValue, int_limit ) * 2.54 );
// Altium's internal precision is 0.1uinch. KiCad's is 1nm. Round to nearest 10nm to clean
// up most rounding errors. This allows lossless conversion of increments of 0.05mils and
// 0.01um.
return KiROUND( (double) iu / 10.0 ) * 10;
}
int ALTIUM_PROPS_UTILS::ReadInt( const std::map<wxString, wxString>& aProps, const wxString& aKey,
int aDefault )
{
const std::map<wxString, wxString>::const_iterator& value = aProps.find( aKey );
return value == aProps.end() ? aDefault : wxAtoi( value->second );
}
double ALTIUM_PROPS_UTILS::ReadDouble( const std::map<wxString, wxString>& aProps, const wxString& aKey,
double aDefault )
{
const std::map<wxString, wxString>::const_iterator& value = aProps.find( aKey );
if( value == aProps.end() )
return aDefault;
// Locale independent str -> double conversation
std::istringstream istr( (const char*) value->second.mb_str() );
istr.imbue( std::locale::classic() );
double doubleValue;
istr >> doubleValue;
return doubleValue;
}
bool ALTIUM_PROPS_UTILS::ReadBool( const std::map<wxString, wxString>& aProps, const wxString& aKey,
bool aDefault )
{
const std::map<wxString, wxString>::const_iterator& value = aProps.find( aKey );
if( value == aProps.end() )
return aDefault;
else
return value->second == "T" || value->second == "TRUE";
}
int32_t ALTIUM_PROPS_UTILS::ReadKicadUnit( const std::map<wxString, wxString>& aProps,
const wxString& aKey, const wxString& aDefault )
{
const wxString& value = ReadString( aProps, aKey, aDefault );
wxString prefix;
if( !value.EndsWith( "mil", &prefix ) )
{
wxLogError( _( "Unit '%s' does not end with 'mil'." ), value );
return 0;
}
prefix.StartsWith( "+", &prefix );
double mils;
if( !prefix.ToCDouble( &mils ) )
{
wxLogError( _( "Cannot convert '%s' to double." ), prefix );
return 0;
}
return ConvertToKicadUnit( mils * 10000 );
}
wxString ALTIUM_PROPS_UTILS::ReadString( const std::map<wxString, wxString>& aProps,
const wxString& aKey, const wxString& aDefault )
{
const auto& utf8Value = aProps.find( wxString( "%UTF8%" ) + aKey );
if( utf8Value != aProps.end() )
return utf8Value->second;
const auto& value = aProps.find( aKey );
if( value != aProps.end() )
return value->second;
return aDefault;
}
wxString ALTIUM_PROPS_UTILS::ReadUnicodeString( const std::map<wxString, wxString>& aProps,
const wxString& aKey, const wxString& aDefault )
{
const auto& unicodeFlag = aProps.find( wxS( "UNICODE" ) );
if( unicodeFlag != aProps.end() && unicodeFlag->second.Contains( wxS( "EXISTS" ) ) )
{
const auto& unicodeValue = aProps.find( wxString( "UNICODE__" ) + aKey );
if( unicodeValue != aProps.end() )
{
wxArrayString arr = wxSplit( unicodeValue->second, ',', '\0' );
wxString out;
for( wxString part : arr )
out += wxString( wchar_t( wxAtoi( part ) ) );
return out;
}
}
return ReadString( aProps, aKey, aDefault );
}