++new:
Completed a good portion of /new class DIR_LIB_SOURCE. Added an autonomous CMakeLists.txt file to /new, with new-docs target and test program target.
This commit is contained in:
commit
c4a6b4186a
|
@ -4,6 +4,13 @@ KiCad ChangeLog 2010
|
||||||
Please add newer entries at the top, list the date and your name with
|
Please add newer entries at the top, list the date and your name with
|
||||||
email address.
|
email address.
|
||||||
|
|
||||||
|
2010-Dec-19 UPDATE Dick Hollenbeck <dick@softplc.com>
|
||||||
|
================================================================================
|
||||||
|
++new:
|
||||||
|
Completed a good portion of /new class DIR_LIB_SOURCE.
|
||||||
|
Added an autonomous CMakeLists.txt file to /new, with new-docs target and
|
||||||
|
test program target.
|
||||||
|
|
||||||
2010-dec-15, UPDATE Jean-Pierre Charras <jean-pierre.charras@gipsa-lab.inpg.fr>
|
2010-dec-15, UPDATE Jean-Pierre Charras <jean-pierre.charras@gipsa-lab.inpg.fr>
|
||||||
================================================================================
|
================================================================================
|
||||||
Gerbview:
|
Gerbview:
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 SoftPLC Corporation, <dick@softplc.com>
|
||||||
|
* Copyright (C) 2010 Kicad Developers, see change_log.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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KICAD_EXCEPTIONS_H_
|
||||||
|
#define KICAD_EXCEPTIONS_H_
|
||||||
|
|
||||||
|
/* Just exceptions
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <wx/string.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Struct IO_ERROR
|
||||||
|
* is a class used to hold an error message and may be used to throw exceptions
|
||||||
|
* containing meaningful error messages.
|
||||||
|
* @author Dick Hollenbeck
|
||||||
|
*/
|
||||||
|
struct IO_ERROR
|
||||||
|
{
|
||||||
|
wxString errorText;
|
||||||
|
|
||||||
|
IO_ERROR( const wxChar* aMsg ) :
|
||||||
|
errorText( aMsg )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
IO_ERROR( const wxString& aMsg ) :
|
||||||
|
errorText( aMsg )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
IO_ERROR( const char* aMsg ) :
|
||||||
|
errorText( wxConvertMB2WX( aMsg ) )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class PARSE_ERROR
|
||||||
|
* contains a filename or source description, a line number, a character offset,
|
||||||
|
* and an error message.
|
||||||
|
* @author Dick Hollenbeck
|
||||||
|
*/
|
||||||
|
struct PARSE_ERROR : public IO_ERROR
|
||||||
|
{
|
||||||
|
wxString source; ///< filename typically, unless from RAM
|
||||||
|
int lineNumber;
|
||||||
|
int byteIndex; ///< char offset, starting from 1, into the problem line.
|
||||||
|
|
||||||
|
PARSE_ERROR( const wxString& aMsg, const wxString& aSource,
|
||||||
|
int aLineNumber, int aByteIndex ) :
|
||||||
|
IO_ERROR( aMsg ),
|
||||||
|
source( aSource ),
|
||||||
|
lineNumber( aLineNumber )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // KICAD_EXCEPTIONS_H_
|
|
@ -6,9 +6,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#ifndef __INCLUDE__KICAD_STRING_H__
|
#ifndef KICAD_STRING_H_
|
||||||
#define __INCLUDE__KICAD_STRING_H__ 1
|
#define KICAD_STRING_H_
|
||||||
|
|
||||||
|
#include <wx/string.h>
|
||||||
|
|
||||||
char* strupper( char* Text );
|
char* strupper( char* Text );
|
||||||
char* strlower( char* Text );
|
char* strlower( char* Text );
|
||||||
|
@ -102,4 +103,4 @@ int SplitString( wxString strToSplit,
|
||||||
wxString* strDigits,
|
wxString* strDigits,
|
||||||
wxString* strEnd );
|
wxString* strEnd );
|
||||||
|
|
||||||
#endif // __INCLUDE__KICAD_STRING_H__
|
#endif // KICAD_STRING_H_
|
||||||
|
|
|
@ -37,30 +37,10 @@
|
||||||
// I really did not want to be dependent on wxWidgets in richio
|
// I really did not want to be dependent on wxWidgets in richio
|
||||||
// but the errorText needs to be wide char so wxString rules.
|
// but the errorText needs to be wide char so wxString rules.
|
||||||
#include <wx/wx.h>
|
#include <wx/wx.h>
|
||||||
#include <cstdio> // FILE
|
#include <cstdio>
|
||||||
|
#include <kicad_exceptions.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Struct IO_ERROR
|
|
||||||
* is a class used to hold an error message and may be used to throw exceptions
|
|
||||||
* containing meaningful error messages.
|
|
||||||
*/
|
|
||||||
struct IO_ERROR
|
|
||||||
{
|
|
||||||
wxString errorText;
|
|
||||||
|
|
||||||
IO_ERROR( const wxChar* aMsg ) :
|
|
||||||
errorText( aMsg )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
IO_ERROR( const wxString& aMsg ) :
|
|
||||||
errorText( aMsg )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#define LINE_READER_LINE_DEFAULT_MAX 100000
|
#define LINE_READER_LINE_DEFAULT_MAX 100000
|
||||||
#define LINE_READER_LINE_INITIAL_SIZE 5000
|
#define LINE_READER_LINE_INITIAL_SIZE 5000
|
||||||
|
|
||||||
|
@ -234,18 +214,19 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class OUTPUTFORMATTER
|
* Class OUTPUTFORMATTER
|
||||||
* is an important interface (abstract) class used to output UTF8 text in a convenient
|
* is an important interface (abstract) class used to output UTF8 text in
|
||||||
* way. The primary interface is "printf() - like" but with support for indentation
|
* a convenient way. The primary interface is "printf() - like" but
|
||||||
* control. The destination of the 8 bit wide text is up to the implementer.
|
* with support for indentation control. The destination of the 8 bit
|
||||||
|
* wide text is up to the implementer.
|
||||||
* <p>
|
* <p>
|
||||||
* The implementer only has to implement the write() function, but can also optionaly
|
* The implementer only has to implement the write() function, but can
|
||||||
* re-implement GetQuoteChar().
|
* also optionally re-implement GetQuoteChar().
|
||||||
* <p>
|
* <p>
|
||||||
* If you want to output a wxString, then use CONV_TO_UTF8() on it before passing
|
* If you want to output a wxString, then use CONV_TO_UTF8() on it
|
||||||
* it as an argument to Print().
|
* before passing it as an argument to Print().
|
||||||
* <p>
|
* <p>
|
||||||
* Since this is an abstract interface, only classes derived from this one
|
* Since this is an abstract interface, only classes derived from
|
||||||
* may actually be used.
|
* this one may actually be used.
|
||||||
*/
|
*/
|
||||||
class OUTPUTFORMATTER
|
class OUTPUTFORMATTER
|
||||||
{
|
{
|
||||||
|
@ -307,7 +288,7 @@ public:
|
||||||
* Function Print
|
* Function Print
|
||||||
* formats and writes text to the output stream.
|
* formats and writes text to the output stream.
|
||||||
*
|
*
|
||||||
* @param nestLevel The multiple of spaces to preceed the output with.
|
* @param nestLevel The multiple of spaces to precede the output with.
|
||||||
* @param fmt A printf() style format string.
|
* @param fmt A printf() style format string.
|
||||||
* @param ... a variable list of parameters that will get blended into
|
* @param ... a variable list of parameters that will get blended into
|
||||||
* the output under control of the format string.
|
* the output under control of the format string.
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
|
||||||
|
set( STAND_ALONE true )
|
||||||
|
|
||||||
|
if( STAND_ALONE )
|
||||||
|
project(kicad-new)
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 2.6.4 FATAL_ERROR)
|
||||||
|
|
||||||
|
set( PROJECT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../ )
|
||||||
|
|
||||||
|
# Path to local CMake modules.
|
||||||
|
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMakeModules)
|
||||||
|
|
||||||
|
include(CheckFindPackageResult)
|
||||||
|
|
||||||
|
find_package(Doxygen)
|
||||||
|
|
||||||
|
# On Apple only wxwidgets 2.9 or higher doesn't need to find aui part of base
|
||||||
|
if(APPLE)
|
||||||
|
find_package(wxWidgets COMPONENTS gl adv html core net base xml QUIET)
|
||||||
|
else()
|
||||||
|
find_package(wxWidgets COMPONENTS gl aui adv html core net base xml QUIET)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
check_find_package_result( wxWidgets_FOUND "wxWidgets" )
|
||||||
|
|
||||||
|
# Include wxWidgets macros.
|
||||||
|
include( ${wxWidgets_USE_FILE} )
|
||||||
|
|
||||||
|
include_directories( ${PROJECT_SOURCE_DIR}/include )
|
||||||
|
|
||||||
|
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||||
|
# Set default flags for Release build.
|
||||||
|
set(CMAKE_C_FLAGS_RELEASE "-Wall -O2 -DNDEBUG ")
|
||||||
|
set(CMAKE_CXX_FLAGS_RELEASE "-Wall -O2 -DNDEBUG")
|
||||||
|
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "-s -static-libgcc")
|
||||||
|
|
||||||
|
# Set default flags for Debug build.
|
||||||
|
set(CMAKE_C_FLAGS_DEBUG "-Wall -g3 -ggdb3 -DDEBUG")
|
||||||
|
set(CMAKE_CXX_FLAGS_DEBUG "-Wall -g3 -ggdb3 -DDEBUG")
|
||||||
|
endif(CMAKE_COMPILER_IS_GNUCXX)
|
||||||
|
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#================================================
|
||||||
|
# Doxygen Output
|
||||||
|
#================================================
|
||||||
|
if(DOXYGEN_FOUND)
|
||||||
|
add_custom_target( new-docs ${DOXYGEN_EXECUTABLE}
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
DEPENDS Doxyfile )
|
||||||
|
else(DOXYGEN_FOUND)
|
||||||
|
message( STATUS "WARNING: Doxygen not found - new-docs (Source Docs) target not created" )
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
include_directories( ${CMAKE_SOURCE_DIR} )
|
||||||
|
|
||||||
|
add_executable( test_dir_lib_source sch_dir_lib_source.cpp )
|
||||||
|
#add_executable( test_dir_lib_source EXCLUDE_FROM_ALL sch_dir_lib_source.cpp )
|
||||||
|
|
||||||
|
target_link_libraries( test_dir_lib_source ${wxWidgets_LIBRARIES} )
|
||||||
|
|
291
new/design.h
291
new/design.h
|
@ -382,14 +382,6 @@ const STRING StrEmpty = "";
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* Class PARSE_ERROR
|
|
||||||
* contains a filename or source description, a line number, a character offset,
|
|
||||||
* and an error message.
|
|
||||||
*/
|
|
||||||
struct PARSE_ERROR : public IO_ERROR
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
/** @} exception_types Exception Types */
|
/** @} exception_types Exception Types */
|
||||||
|
|
||||||
|
@ -624,113 +616,6 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class LIB_SOURCE
|
|
||||||
* is an abstract class from which implementation specific LIB_SOURCEs
|
|
||||||
* may be derived, one for each kind of library type allowed in the library table.
|
|
||||||
* The class name stems from the fact that this interface only provides READ ONLY
|
|
||||||
* functions.
|
|
||||||
*/
|
|
||||||
class LIB_SOURCE
|
|
||||||
{
|
|
||||||
friend class LIBS; ///< the LIB factory is LIBS::GetLibrary()
|
|
||||||
friend class LIB; ///< the LIB uses these functions.
|
|
||||||
|
|
||||||
protected: ///< derived classes must implement
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function GetSourceType
|
|
||||||
* retuns type library table entry's type for library source.
|
|
||||||
*/
|
|
||||||
const STRING& GetSourceType() { return sourceType ; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function ReadPart
|
|
||||||
* fetches @a aPartName's s-expression into @a aResult after clear()ing aResult.
|
|
||||||
*/
|
|
||||||
virtual void ReadPart( STRING* aResult, const STRING& aPartName, const STRING& aRev=StrEmpty ) throw( IO_ERROR ) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function ReadParts
|
|
||||||
* fetches the s-expressions for each part given in @a aPartNames, into @a aResults,
|
|
||||||
* honoring the array indices respectfully.
|
|
||||||
* @param aPartNames is a list of part names, one name per list element.
|
|
||||||
* @param aResults receives the s-expressions
|
|
||||||
*/
|
|
||||||
virtual void ReadParts( STRING_TOKS* aResults, const STRINGS& aPartNames ) throw( IO_ERROR ) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function GetCategories
|
|
||||||
* fetches all categories present in the library source into @a aResults
|
|
||||||
*/
|
|
||||||
virtual void GetCategories( STRING_TOKS* aResults ) throw( IO_ERROR ) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function GetCategoricalPartNames
|
|
||||||
* fetches all the part names for @a aCategory, which was returned by GetCategories().
|
|
||||||
*
|
|
||||||
* @param aCategory is a subdividing navigator within the library source,
|
|
||||||
* but may default to empty which will be taken to mean all categories.
|
|
||||||
*
|
|
||||||
* @param aResults is a place to put the fetched result, one category per STRING.
|
|
||||||
*/
|
|
||||||
virtual void GetCategoricalPartNames( STRING_TOKS* aResults,
|
|
||||||
const STRING& aCategory=StrEmpty ) throw( IO_ERROR ) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function GetRevisions
|
|
||||||
* fetches all revisions for @a aPartName into @a aResults. Revisions are strings
|
|
||||||
* like "rev12", "rev279", and are library source agnostic. These
|
|
||||||
*/
|
|
||||||
virtual void GetRevisions( STRING_TOKS* aResults,
|
|
||||||
const STRING& aPartName ) throw( IO_ERROR ) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function FindParts
|
|
||||||
* fetches part names for all parts matching the criteria given in @a
|
|
||||||
* aQuery, into @a aResults. The query string is designed to be easily marshalled,
|
|
||||||
* i.e. serialized, so that long distance queries can be made with minimal overhead.
|
|
||||||
* The library source needs to have an intelligent friend on the other end if
|
|
||||||
* the actual library data is remotely located, otherwise it will be too slow
|
|
||||||
* to honor this portion of the API contract.
|
|
||||||
*
|
|
||||||
* @param aQuery is a string holding a domain specific query language expression. One candidate
|
|
||||||
* here is an s-expression that uses (and ..) and (or ..) operators and uses them as RPN. For example
|
|
||||||
* "(and (footprint 0805)(value 33ohm)(category passives))".
|
|
||||||
* The UI can shield the user from this if it wants.
|
|
||||||
*
|
|
||||||
* @param aResults is a place to put the fetched part names, one part per STRING.
|
|
||||||
*/
|
|
||||||
virtual void FindParts( STRING_TOKS* aResults,
|
|
||||||
const STRING& aQuery ) throw( IO_ERROR ) = 0;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
STRING sourceType;
|
|
||||||
STRING sourceURI;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class DIR_LIB_SOURCE
|
|
||||||
* implements a LIB_SOURCE in a file system directory.
|
|
||||||
*/
|
|
||||||
class DIR_LIB_SOURCE : public LIB_SOURCE
|
|
||||||
{
|
|
||||||
friend class LIBS; ///< LIBS::GetLib() can construct one.
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor DIR_LIB_SOURCE( const STRING& aDirectoryPath )
|
|
||||||
* sets up a LIB_SOURCE using aDirectoryPath in a file system.
|
|
||||||
* @see LIBS::GetLibrary().
|
|
||||||
*
|
|
||||||
* @param aDirectoryPath is a full pathname of a directory which contains
|
|
||||||
* the library source of part files. Examples might be "C:\kicad_data\mylib" or
|
|
||||||
* "/home/designer/mylibdir".
|
|
||||||
*/
|
|
||||||
DIR_LIB_SOURCE( const STRING& aDirectoryPath ) throws( IO_ERROR );
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -781,38 +666,6 @@ protected:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class LIB_SINK
|
|
||||||
* is an abstract class from which implementation specific LIB_SINKs
|
|
||||||
* may be derived, one for each kind of library type in the library table that
|
|
||||||
* supports writing. The class name stems from the fact that this interface
|
|
||||||
* only provides WRITE functions.
|
|
||||||
*/
|
|
||||||
class LIB_SINK
|
|
||||||
{
|
|
||||||
friend class LIB; ///< only the LIB uses these functions.
|
|
||||||
|
|
||||||
protected: ///< derived classes must implement
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function WritePart
|
|
||||||
* saves the part to non-volatile storage. @a aPartName may have the revision
|
|
||||||
* portion present. If it is not present, and a overwrite of an existhing
|
|
||||||
* part is done, then LIB::ReloadPart() must be called on this same part
|
|
||||||
* and all parts that inherit it must be reparsed.
|
|
||||||
* @return STRING - if the LIB_SINK support revision numbering, then return a
|
|
||||||
* evision name that was next in the sequence, e.g. "rev22", else StrEmpty.
|
|
||||||
*/
|
|
||||||
virtual STRING WritePart( const STRING& aPartName,
|
|
||||||
const STRING& aSExpression ) throw( IO_ERROR ) = 0;
|
|
||||||
|
|
||||||
|
|
||||||
protected:
|
|
||||||
STRING sinkType;
|
|
||||||
STRING sinkURI;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class LIBS
|
* Class LIBS
|
||||||
* houses a handful of functions that manage all the RAM resident LIBs, and
|
* houses a handful of functions that manage all the RAM resident LIBs, and
|
||||||
|
@ -863,150 +716,6 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class LIB
|
|
||||||
* is a cache of parts, and because the LIB_SOURCE is abstracted, there
|
|
||||||
* should be no need to extend from this class in any case except for the
|
|
||||||
* PARTS_LIST.
|
|
||||||
*/
|
|
||||||
class LIB
|
|
||||||
{
|
|
||||||
friend class LIBS; ///< the LIB factory is LIBS::GetLibrary()
|
|
||||||
|
|
||||||
protected: // constructor is not public, called from LIBS only.
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor LIB
|
|
||||||
* is not public and is only called from LIBS::GetLib()
|
|
||||||
*
|
|
||||||
* @param aLogicalLibrary is the name of a well know logical library, and is
|
|
||||||
* known because it already exists in the library table.
|
|
||||||
*
|
|
||||||
* @param aSource is an open LIB_SOURCE whose ownership is
|
|
||||||
* given over to this LIB.
|
|
||||||
*
|
|
||||||
* @param aSink is an open LIB_SINK whose ownership is given over
|
|
||||||
* to this LIB, and it is normally NULL.
|
|
||||||
*/
|
|
||||||
LIB( const STRING& aLogicalLibrary, LIB_SOURCE* aSource, LIB_SINK* aSink=NULL ) :
|
|
||||||
name( aLogicalLibrary ),
|
|
||||||
source( aSource ),
|
|
||||||
sink( aSink )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~LIB()
|
|
||||||
{
|
|
||||||
delete source;
|
|
||||||
delete sink;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function HasSink
|
|
||||||
* returns true if this library has write/save capability. Most LIBs
|
|
||||||
* are read only.
|
|
||||||
*/
|
|
||||||
bool HasSink() { return sink != NULL; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function LogicalName
|
|
||||||
* returns the logical name of this LIB.
|
|
||||||
*/
|
|
||||||
STRING LogicalName();
|
|
||||||
|
|
||||||
//-----<use delegates: source and sink>---------------------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function GetPart
|
|
||||||
* returns a PART given @a aPartName, such as "passives/R".
|
|
||||||
* @param aPartName is local to this LIB and does not have the logical
|
|
||||||
* library name prefixed.
|
|
||||||
*/
|
|
||||||
const PART* GetPart( const STRING& aPartName ) throw( IO_ERROR );
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function ReloadPart
|
|
||||||
* will reload the part assuming the library source has a changed content
|
|
||||||
* for it.
|
|
||||||
*/
|
|
||||||
void ReloadPart( PART* aPart ) throw( IO_ERROR );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function GetCategories
|
|
||||||
* returns all categories of parts within this LIB into @a aResults.
|
|
||||||
*/
|
|
||||||
STRINGS GetCategories() throw( IO_ERROR );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function GetCategoricalPartNames
|
|
||||||
* returns the part names for @a aCategory, and at the same time
|
|
||||||
* creates cache entries for the very same parts if they do not already exist
|
|
||||||
* in this LIB (i.e. cache).
|
|
||||||
*/
|
|
||||||
STRINGS GetCategoricalPartNames( const STRING& aCategory=StrEmpty ) throw( IO_ERROR );
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//-----<.use delegates: source and sink>--------------------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function WritePart
|
|
||||||
* saves the part to non-volatile storage and returns the next new revision
|
|
||||||
* name in the sequence established by the LIB_SINK.
|
|
||||||
*/
|
|
||||||
virtual STRING WritePart( PART* aPart ) throw( IO_ERROR );
|
|
||||||
|
|
||||||
virtual void SetPartBody( PART* aPart, const STRING& aSExpression ) throw( IO_ERROR );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function GetRevisions
|
|
||||||
* returns the revisions of @a aPartName that are present in this LIB.
|
|
||||||
* The returned STRINGS will look like "rev1", "rev2", etc.
|
|
||||||
*/
|
|
||||||
STRINGS GetRevisions( const STRING& aPartName ) throw( IO_ERROR );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function FindParts
|
|
||||||
* returns part names for all parts matching the criteria given in @a
|
|
||||||
* aQuery, into @a aResults. The query string is designed to be easily marshalled,
|
|
||||||
* i.e. serialized, so that long distance queries can be made with minimal overhead.
|
|
||||||
* The library source needs to have an intelligent friend on the other end if
|
|
||||||
* the actual library data is remotely located, otherwise it will be too slow
|
|
||||||
* to honor this portion of the API contract.
|
|
||||||
*
|
|
||||||
* @param aQuery is a string holding a domain specific language expression. One candidate
|
|
||||||
* here is an RPN s-expression that uses (and ..) and (or ..) operators. For example
|
|
||||||
* "(and (footprint 0805)(value 33ohm)(category passives))"
|
|
||||||
*/
|
|
||||||
STRINGS FindParts( const STRING& aQuery ) throw( IO_ERROR );
|
|
||||||
{
|
|
||||||
// run the query on the cached data first for any PARTS which are fully
|
|
||||||
// parsed (i.e. cached), then on the LIB_SOURCE to find any that
|
|
||||||
// are not fully parsed, then unify the results.
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
STRING fetch; // scratch, used to fetch things, grows to worst case size.
|
|
||||||
STRINGS vfetch; // scratch, used to fetch things.
|
|
||||||
|
|
||||||
LIB_SOURCE* source;
|
|
||||||
LIB_SINK* sink;
|
|
||||||
|
|
||||||
STRING name;
|
|
||||||
STRING libraryType;
|
|
||||||
STRING libraryURI;
|
|
||||||
|
|
||||||
STRINGS categories;
|
|
||||||
|
|
||||||
PARTS parts;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class PARTS_LIST
|
* Class PARTS_LIST
|
||||||
* is a LIB which resides in a SCHEMATIC, and it is a table model for a
|
* is a LIB which resides in a SCHEMATIC, and it is a table model for a
|
||||||
|
|
|
@ -0,0 +1,330 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 SoftPLC Corporation, <dick@softplc.com>
|
||||||
|
* Copyright (C) 2010 Kicad Developers, see change_log.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
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Note: this LIB_SOURCE implementation relies on the posix specified opendir() and
|
||||||
|
related functions rather than wx functions which might do the same thing. This
|
||||||
|
is because I did not want to become very dependent on wxWidgets at such a low
|
||||||
|
level as this, in case someday this code needs to be used on kde or whatever.
|
||||||
|
|
||||||
|
Mingw and unix, linux, & osx will all have these posix functions.
|
||||||
|
MS Visual Studio may need the posix compatible opendir() functions brought in
|
||||||
|
http://www.softagalleria.net/dirent.php
|
||||||
|
wx has these but they are based on wxString which can be wchar_t based and wx should
|
||||||
|
not be introduced at a level this low.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sch_dir_lib_source.h>
|
||||||
|
using namespace SCH;
|
||||||
|
|
||||||
|
#include <kicad_exceptions.h>
|
||||||
|
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <cstring>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class DIR_WRAP
|
||||||
|
* provides a destructor which may be invoked if an exception is thrown.
|
||||||
|
*/
|
||||||
|
class DIR_WRAP
|
||||||
|
{
|
||||||
|
DIR* dir;
|
||||||
|
|
||||||
|
public:
|
||||||
|
DIR_WRAP( DIR* aDir ) : dir( aDir ) {}
|
||||||
|
|
||||||
|
~DIR_WRAP()
|
||||||
|
{
|
||||||
|
if( dir )
|
||||||
|
closedir( dir );
|
||||||
|
}
|
||||||
|
|
||||||
|
DIR* operator->() { return dir; }
|
||||||
|
DIR* operator*() { return dir; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class FILE_WRAP
|
||||||
|
* provides a destructor which may be invoked if an exception is thrown.
|
||||||
|
*/
|
||||||
|
class FILE_WRAP
|
||||||
|
{
|
||||||
|
int fh;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FILE_WRAP( int aFileHandle ) : fh( aFileHandle ) {}
|
||||||
|
~FILE_WRAP()
|
||||||
|
{
|
||||||
|
if( fh != -1 )
|
||||||
|
close( fh );
|
||||||
|
}
|
||||||
|
|
||||||
|
operator int () { return fh; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function strrstr
|
||||||
|
* finds the last instance of needle in haystack, if any.
|
||||||
|
*/
|
||||||
|
static const char* strrstr( const char* haystack, const char* needle )
|
||||||
|
{
|
||||||
|
const char* ret = 0;
|
||||||
|
const char* next = haystack;
|
||||||
|
|
||||||
|
// find last instance of haystack
|
||||||
|
while( (next = strstr( next, needle )) != 0 )
|
||||||
|
{
|
||||||
|
ret = next;
|
||||||
|
++next; // don't keep finding the same one.
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const char* endsWithRev( const char* cp, const char* limit )
|
||||||
|
{
|
||||||
|
// find last instance of ".rev"
|
||||||
|
cp = strrstr( cp, ".rev" );
|
||||||
|
if( cp )
|
||||||
|
{
|
||||||
|
const char* rev = cp + 1;
|
||||||
|
|
||||||
|
cp += sizeof( ".rev" )-1;
|
||||||
|
|
||||||
|
while( isdigit( *cp ) )
|
||||||
|
++cp;
|
||||||
|
|
||||||
|
if( cp != limit ) // there is garbage after "revN.."
|
||||||
|
rev = 0;
|
||||||
|
|
||||||
|
return rev;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool DIR_LIB_SOURCE::makePartFileName( const char* aEntry,
|
||||||
|
const STRING& aCategory, STRING* aPartName )
|
||||||
|
{
|
||||||
|
const char* cp = strrstr( aEntry, ".part" );
|
||||||
|
|
||||||
|
// if base name is not empty, contains ".part", && cp is not NULL
|
||||||
|
if( cp > aEntry )
|
||||||
|
{
|
||||||
|
const char* limit = cp + strlen( cp );
|
||||||
|
|
||||||
|
// if file extension is exactly ".part", and no rev
|
||||||
|
if( cp==limit-5 )
|
||||||
|
{
|
||||||
|
if( aCategory.size() )
|
||||||
|
*aPartName = aCategory + "/";
|
||||||
|
else
|
||||||
|
aPartName->clear();
|
||||||
|
|
||||||
|
aPartName->append( aEntry, cp - aEntry );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if versioning, test for a trailing "revN.." type of string
|
||||||
|
if( useVersioning )
|
||||||
|
{
|
||||||
|
const char* rev = endsWithRev( cp + sizeof(".part") - 1, limit );
|
||||||
|
if( rev )
|
||||||
|
{
|
||||||
|
if( aCategory.size() )
|
||||||
|
*aPartName = aCategory + "/";
|
||||||
|
else
|
||||||
|
aPartName->clear();
|
||||||
|
|
||||||
|
aPartName->append( aEntry, cp - aEntry );
|
||||||
|
aPartName->append( "/" );
|
||||||
|
aPartName->append( rev );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isCategoryName( const char* aName )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define MAX_PART_FILE_SIZE (1*1024*1024) // sanity check
|
||||||
|
|
||||||
|
DIR_LIB_SOURCE::DIR_LIB_SOURCE( const STRING& aDirectoryPath, bool doUseVersioning )
|
||||||
|
throw( IO_ERROR )
|
||||||
|
{
|
||||||
|
useVersioning = doUseVersioning;
|
||||||
|
sourceURI = aDirectoryPath;
|
||||||
|
sourceType = "dir";
|
||||||
|
|
||||||
|
if( sourceURI.size() == 0 )
|
||||||
|
{
|
||||||
|
throw( IO_ERROR( "aDirectoryPath cannot be empty" ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove any trailing separator, so we can add it back later without ambiguity
|
||||||
|
if( strchr( "/\\", sourceURI[sourceURI.size()-1] ) )
|
||||||
|
sourceURI.erase( sourceURI.size()-1 );
|
||||||
|
|
||||||
|
doOneDir( "" );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DIR_LIB_SOURCE::~DIR_LIB_SOURCE()
|
||||||
|
{
|
||||||
|
// delete the sweet STRINGS, which "sweets" owns by pointer.
|
||||||
|
for( DIR_CACHE::iterator it = sweets.begin(); it != sweets.end(); ++it )
|
||||||
|
{
|
||||||
|
delete it->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DIR_LIB_SOURCE::Show()
|
||||||
|
{
|
||||||
|
printf( "categories:\n" );
|
||||||
|
for( STRINGS::const_iterator it = categories.begin(); it!=categories.end(); ++it )
|
||||||
|
printf( " '%s'\n", it->c_str() );
|
||||||
|
|
||||||
|
printf( "\n" );
|
||||||
|
printf( "parts:\n" );
|
||||||
|
for( DIR_CACHE::const_iterator it = sweets.begin(); it != sweets.end(); ++it )
|
||||||
|
{
|
||||||
|
printf( " '%s'\n", it->first.c_str() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DIR_LIB_SOURCE::doOneDir( const STRING& aCategory ) throw( IO_ERROR )
|
||||||
|
{
|
||||||
|
STRING curDir = sourceURI;
|
||||||
|
|
||||||
|
if( aCategory.size() )
|
||||||
|
curDir += "/" + aCategory;
|
||||||
|
|
||||||
|
DIR_WRAP dir = opendir( curDir.c_str() );
|
||||||
|
|
||||||
|
if( !*dir )
|
||||||
|
{
|
||||||
|
STRING msg = strerror( errno );
|
||||||
|
msg += "; scanning directory " + curDir;
|
||||||
|
throw( IO_ERROR( msg.c_str() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
struct stat fs;
|
||||||
|
|
||||||
|
STRING partName;
|
||||||
|
STRING fileName;
|
||||||
|
|
||||||
|
dirent* entry;
|
||||||
|
|
||||||
|
while( (entry = readdir( *dir )) != NULL )
|
||||||
|
{
|
||||||
|
if( !strcmp( ".", entry->d_name ) || !strcmp( "..", entry->d_name ) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
fileName = curDir + "/" + entry->d_name;
|
||||||
|
|
||||||
|
//D( printf("name: '%s'\n", fileName.c_str() );)
|
||||||
|
|
||||||
|
if( !stat( fileName.c_str(), &fs ) )
|
||||||
|
{
|
||||||
|
if( S_ISREG( fs.st_mode ) && makePartFileName( entry->d_name, aCategory, &partName ) )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
if( sweets.find( partName ) != sweets.end() )
|
||||||
|
{
|
||||||
|
STRING msg = partName;
|
||||||
|
msg += " has already been encountered";
|
||||||
|
throw IO_ERROR( msg.c_str() );
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
sweets[partName] = NULL; // NULL for now, load the sweet later.
|
||||||
|
//D( printf("part: %s\n", partName.c_str() );)
|
||||||
|
}
|
||||||
|
|
||||||
|
else if( S_ISDIR( fs.st_mode ) && !aCategory.size() && isCategoryName( entry->d_name ) )
|
||||||
|
{
|
||||||
|
// only one level of recursion is used, controlled by the
|
||||||
|
// emptiness of aCategory.
|
||||||
|
//D( printf("category: %s\n", entry->d_name );)
|
||||||
|
categories.push_back( entry->d_name );
|
||||||
|
doOneDir( entry->d_name );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//D( printf( "ignoring %s\n", entry->d_name );)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if 1 || defined( TEST_DIR_LIB_SOURCE )
|
||||||
|
|
||||||
|
int main( int argc, char** argv )
|
||||||
|
{
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DIR_LIB_SOURCE uut( argv[1] ? argv[1] : "", true );
|
||||||
|
uut.Show();
|
||||||
|
}
|
||||||
|
|
||||||
|
catch( IO_ERROR ioe )
|
||||||
|
{
|
||||||
|
printf( "exception: %s\n", (const char*) wxConvertWX2MB( ioe.errorText ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,149 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||||
|
* Copyright (C) 2010 Kicad Developers, see change_log.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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DIR_LIB_SOURCE_H_
|
||||||
|
#define DIR_LIB_SOURCE_H_
|
||||||
|
|
||||||
|
|
||||||
|
#include <sch_lib.h>
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type DIR_CACHE
|
||||||
|
* is a tuple, where the key is partname (prefixed with the category if any),
|
||||||
|
* and value is pointer to Sweet string which is loaded lazily, so can be NULL
|
||||||
|
* until loaded.
|
||||||
|
*/
|
||||||
|
typedef std::map< STRING, STRING* > DIR_CACHE;
|
||||||
|
|
||||||
|
|
||||||
|
namespace SCH {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class DIR_LIB_SOURCE
|
||||||
|
* implements a LIB_SOURCE in a file system directory.
|
||||||
|
*
|
||||||
|
* @author Dick Hollenbeck
|
||||||
|
*/
|
||||||
|
class DIR_LIB_SOURCE : public LIB_SOURCE
|
||||||
|
{
|
||||||
|
friend class LIBS; ///< LIBS::GetLib() can construct one.
|
||||||
|
|
||||||
|
bool useVersioning; ///< use files with extension ".revNNN..", else not
|
||||||
|
|
||||||
|
DIR_CACHE sweets;
|
||||||
|
STRINGS categories;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function isPartFileName
|
||||||
|
* returns true iff aName is a valid part file name.
|
||||||
|
*/
|
||||||
|
bool isPartFileName( const char* aName );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function makePartFileName
|
||||||
|
* returns true iff aEntry holds a valid part filename, in the form of
|
||||||
|
* "someroot.part[.revNNNN]" where NNN are number characters [0-9]
|
||||||
|
* @param aEntry is the raw directory entry without path information.
|
||||||
|
* @param aCategory is the last portion of the directory path.
|
||||||
|
* @param aPartName is where to put a part name, assuming aEntry is legal.
|
||||||
|
* @return bool - true only if aEntry is a legal part file name.
|
||||||
|
*/
|
||||||
|
bool makePartFileName( const char* aEntry,
|
||||||
|
const STRING& aCategory, STRING* aPartName );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function doOneDir
|
||||||
|
* loads part names [and categories] from a directory given by
|
||||||
|
* "sourceURI + '/' + category"
|
||||||
|
* Categories are only loaded if processing the top most directory because
|
||||||
|
* only one level of categories are supported. We know we are in the
|
||||||
|
* top most directory if aCategory is empty.
|
||||||
|
*/
|
||||||
|
void doOneDir( const STRING& aCategory ) throw( IO_ERROR );
|
||||||
|
|
||||||
|
//protected:
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor DIR_LIB_SOURCE( const STRING& aDirectoryPath )
|
||||||
|
* sets up a LIB_SOURCE using aDirectoryPath in a file system.
|
||||||
|
* @see LIBS::GetLibrary().
|
||||||
|
*
|
||||||
|
* @param aDirectoryPath is a full file pathname of a directory which contains
|
||||||
|
* the library source of part files. Examples might be "C:\kicad_data\mylib" or
|
||||||
|
* "/home/designer/mylibdir". This is not a URI, but an OS specific path that
|
||||||
|
* can be given to opendir().
|
||||||
|
*
|
||||||
|
* @param doUseVersioning if true means support versioning in the directory tree, otherwise
|
||||||
|
* only a single version of each part is recognized.
|
||||||
|
*/
|
||||||
|
DIR_LIB_SOURCE( const STRING& aDirectoryPath, bool doUseVersioning = false )
|
||||||
|
throw( IO_ERROR );
|
||||||
|
|
||||||
|
~DIR_LIB_SOURCE();
|
||||||
|
|
||||||
|
//-----<LIB_SOURCE implementation functions >------------------------------
|
||||||
|
|
||||||
|
void ReadPart( STRING* aResult, const STRING& aPartName, const STRING& aRev=StrEmpty )
|
||||||
|
throw( IO_ERROR )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReadParts( STRING_TOKS* aResults, const STRINGS& aPartNames )
|
||||||
|
throw( IO_ERROR )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetCategories( STRING_TOKS* aResults ) throw( IO_ERROR )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetCategoricalPartNames( STRING_TOKS* aResults,
|
||||||
|
const STRING& aCategory=StrEmpty ) throw( IO_ERROR )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetRevisions( STRING_TOKS* aResults, const STRING& aPartName ) throw( IO_ERROR )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void FindParts( STRING_TOKS* aResults, const STRING& aQuery ) throw( IO_ERROR )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----</LIB_SOURCE implementation functions >------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function Show
|
||||||
|
* will output a debug dump of contents.
|
||||||
|
*/
|
||||||
|
void Show();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace SCH
|
||||||
|
|
||||||
|
#endif // DIR_LIB_SOURCE_H_
|
|
@ -0,0 +1,351 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||||
|
* Copyright (C) 2010 Kicad Developers, see change_log.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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SCH_LIB_H_
|
||||||
|
#define SCH_LIB_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <deque>
|
||||||
|
|
||||||
|
#include <kicad_exceptions.h>
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
#define D(x) x
|
||||||
|
#else
|
||||||
|
#define D(x) // nothing
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
typedef std::string STRING;
|
||||||
|
typedef std::deque<STRING> STRINGS;
|
||||||
|
typedef STRINGS STRING_TOKS;
|
||||||
|
|
||||||
|
extern const STRING StrEmpty;
|
||||||
|
|
||||||
|
namespace SCH {
|
||||||
|
|
||||||
|
class PART;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class LIB_SOURCE
|
||||||
|
* is an abstract class from which implementation specific LIB_SOURCEs
|
||||||
|
* may be derived, one for each kind of library type allowed in the library table.
|
||||||
|
* The class name stems from the fact that this interface only provides READ ONLY
|
||||||
|
* functions.
|
||||||
|
*
|
||||||
|
* @author Dick Hollenbeck
|
||||||
|
*/
|
||||||
|
class LIB_SOURCE
|
||||||
|
{
|
||||||
|
friend class LIBS; ///< the LIB factory is LIBS::GetLibrary()
|
||||||
|
friend class LIB; ///< the LIB uses these functions.
|
||||||
|
|
||||||
|
protected: ///< derived classes must implement
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetSourceType
|
||||||
|
* returns the library table entry's type for this library source.
|
||||||
|
*/
|
||||||
|
const STRING& GetSourceType() { return sourceType; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetSourceURI
|
||||||
|
* returns absolute location of the library source.
|
||||||
|
*/
|
||||||
|
const STRING& GetSourceURI() { return sourceURI; }
|
||||||
|
|
||||||
|
//-----<abstract for implementors>---------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function ReadPart
|
||||||
|
* fetches @a aPartName's s-expression into @a aResult after clear()ing aResult.
|
||||||
|
*/
|
||||||
|
virtual void ReadPart( STRING* aResult, const STRING& aPartName, const STRING& aRev=StrEmpty )
|
||||||
|
throw( IO_ERROR ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function ReadParts
|
||||||
|
* fetches the s-expressions for each part given in @a aPartNames, into @a aResults,
|
||||||
|
* honoring the array indices respectfully.
|
||||||
|
* @param aPartNames is a list of part names, one name per list element.
|
||||||
|
* @param aResults receives the s-expressions
|
||||||
|
*/
|
||||||
|
virtual void ReadParts( STRING_TOKS* aResults, const STRINGS& aPartNames )
|
||||||
|
throw( IO_ERROR ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetCategories
|
||||||
|
* fetches all categories present in the library source into @a aResults
|
||||||
|
*/
|
||||||
|
virtual void GetCategories( STRING_TOKS* aResults )
|
||||||
|
throw( IO_ERROR ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetCategoricalPartNames
|
||||||
|
* fetches all the part names for @a aCategory, which was returned by GetCategories().
|
||||||
|
*
|
||||||
|
* @param aCategory is a subdividing navigator within the library source,
|
||||||
|
* but may default to empty which will be taken to mean all categories.
|
||||||
|
*
|
||||||
|
* @param aResults is a place to put the fetched result, one category per STRING.
|
||||||
|
*/
|
||||||
|
virtual void GetCategoricalPartNames( STRING_TOKS* aResults, const STRING& aCategory=StrEmpty )
|
||||||
|
throw( IO_ERROR ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetRevisions
|
||||||
|
* fetches all revisions for @a aPartName into @a aResults. Revisions are strings
|
||||||
|
* like "rev12", "rev279", and are library source agnostic. These
|
||||||
|
*/
|
||||||
|
virtual void GetRevisions( STRING_TOKS* aResults, const STRING& aPartName )
|
||||||
|
throw( IO_ERROR ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function FindParts
|
||||||
|
* fetches part names for all parts matching the criteria given in @a
|
||||||
|
* aQuery, into @a aResults. The query string is designed to be easily marshalled,
|
||||||
|
* i.e. serialized, so that long distance queries can be made with minimal overhead.
|
||||||
|
* The library source needs to have an intelligent friend on the other end if
|
||||||
|
* the actual library data is remotely located, otherwise it will be too slow
|
||||||
|
* to honor this portion of the API contract.
|
||||||
|
*
|
||||||
|
* @param aQuery is a string holding a domain specific query language expression.
|
||||||
|
* One candidate here is an s-expression that uses (and ..) and (or ..) operators
|
||||||
|
* and uses them as RPN. For example "(and (footprint 0805)(value 33ohm)(category passives))".
|
||||||
|
* The UI can shield the user from this if it wants.
|
||||||
|
*
|
||||||
|
* @param aResults is a place to put the fetched part names, one part per STRING.
|
||||||
|
*/
|
||||||
|
virtual void FindParts( STRING_TOKS* aResults, const STRING& aQuery )
|
||||||
|
throw( IO_ERROR ) = 0;
|
||||||
|
|
||||||
|
//-----</abstract for implementors>--------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
STRING sourceType;
|
||||||
|
STRING sourceURI;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class LIB_SINK
|
||||||
|
* is an abstract class from which implementation specific LIB_SINKs
|
||||||
|
* may be derived, one for each kind of library type in the library table that
|
||||||
|
* supports writing. The class name stems from the fact that this interface
|
||||||
|
* only provides WRITE functions.
|
||||||
|
*
|
||||||
|
* @author Dick Hollenbeck
|
||||||
|
*/
|
||||||
|
class LIB_SINK
|
||||||
|
{
|
||||||
|
friend class LIB; ///< only the LIB uses these functions.
|
||||||
|
|
||||||
|
protected: ///< derived classes must implement
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetSinkType
|
||||||
|
* returns the library table entry's type for this library sink.
|
||||||
|
*/
|
||||||
|
const STRING& GetSinkType() { return sinkType; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetSinkURI
|
||||||
|
* returns absolute location of the library sink.
|
||||||
|
*/
|
||||||
|
const STRING& GetSinkURI() { return sinkURI; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function WritePart
|
||||||
|
* saves the part to non-volatile storage. @a aPartName may have the revision
|
||||||
|
* portion present. If it is not present, and a overwrite of an existhing
|
||||||
|
* part is done, then LIB::ReloadPart() must be called on this same part
|
||||||
|
* and all parts that inherit it must be reparsed.
|
||||||
|
* @return STRING - if the LIB_SINK support revision numbering, then return a
|
||||||
|
* evision name that was next in the sequence, e.g. "rev22", else StrEmpty.
|
||||||
|
*/
|
||||||
|
virtual STRING WritePart( const STRING& aPartName, const STRING& aSExpression )
|
||||||
|
throw( IO_ERROR ) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
STRING sinkType;
|
||||||
|
STRING sinkURI;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class LIB
|
||||||
|
* is a cache of parts, and because the LIB_SOURCE is abstracted, there
|
||||||
|
* should be no need to extend from this class in any case except for the
|
||||||
|
* PARTS_LIST.
|
||||||
|
*
|
||||||
|
* @author Dick Hollenbeck
|
||||||
|
*/
|
||||||
|
class LIB
|
||||||
|
{
|
||||||
|
friend class LIBS; ///< the LIB factory is LIBS::GetLibrary()
|
||||||
|
|
||||||
|
protected: // constructor is not public, called from LIBS only.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor LIB
|
||||||
|
* is not public and is only called from LIBS::GetLib()
|
||||||
|
*
|
||||||
|
* @param aLogicalLibrary is the name of a well know logical library, and is
|
||||||
|
* known because it already exists in the library table.
|
||||||
|
*
|
||||||
|
* @param aSource is an open LIB_SOURCE whose ownership is
|
||||||
|
* given over to this LIB.
|
||||||
|
*
|
||||||
|
* @param aSink is an open LIB_SINK whose ownership is given over
|
||||||
|
* to this LIB, and it is normally NULL.
|
||||||
|
*/
|
||||||
|
LIB( const STRING& aLogicalLibrary, LIB_SOURCE* aSource, LIB_SINK* aSink=NULL ) :
|
||||||
|
name( aLogicalLibrary ),
|
||||||
|
source( aSource ),
|
||||||
|
sink( aSink )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~LIB()
|
||||||
|
{
|
||||||
|
delete source;
|
||||||
|
delete sink;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function HasSink
|
||||||
|
* returns true if this library has write/save capability. Most LIBs
|
||||||
|
* are read only.
|
||||||
|
*/
|
||||||
|
bool HasSink() { return sink != NULL; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function LogicalName
|
||||||
|
* returns the logical name of this LIB.
|
||||||
|
*/
|
||||||
|
STRING LogicalName();
|
||||||
|
|
||||||
|
//-----<use delegates: source and sink>---------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetPart
|
||||||
|
* returns a PART given @a aPartName, such as "passives/R".
|
||||||
|
* @param aPartName is local to this LIB and does not have the logical
|
||||||
|
* library name prefixed.
|
||||||
|
*/
|
||||||
|
const PART* GetPart( const STRING& aPartName ) throw( IO_ERROR );
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function ReloadPart
|
||||||
|
* will reload the part assuming the library source has a changed content
|
||||||
|
* for it.
|
||||||
|
*/
|
||||||
|
void ReloadPart( PART* aPart ) throw( IO_ERROR );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetCategories
|
||||||
|
* returns all categories of parts within this LIB into @a aResults.
|
||||||
|
*/
|
||||||
|
STRINGS GetCategories() throw( IO_ERROR );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetCategoricalPartNames
|
||||||
|
* returns the part names for @a aCategory, and at the same time
|
||||||
|
* creates cache entries for the very same parts if they do not already exist
|
||||||
|
* in this LIB (i.e. cache).
|
||||||
|
*/
|
||||||
|
STRINGS GetCategoricalPartNames( const STRING& aCategory=StrEmpty ) throw( IO_ERROR );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//-----<.use delegates: source and sink>--------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function WritePart
|
||||||
|
* saves the part to non-volatile storage and returns the next new revision
|
||||||
|
* name in the sequence established by the LIB_SINK.
|
||||||
|
*/
|
||||||
|
virtual STRING WritePart( PART* aPart ) throw( IO_ERROR );
|
||||||
|
|
||||||
|
virtual void SetPartBody( PART* aPart, const STRING& aSExpression ) throw( IO_ERROR );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetRevisions
|
||||||
|
* returns the revisions of @a aPartName that are present in this LIB.
|
||||||
|
* The returned STRINGS will look like "rev1", "rev2", etc.
|
||||||
|
*/
|
||||||
|
STRINGS GetRevisions( const STRING& aPartName ) throw( IO_ERROR );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function FindParts
|
||||||
|
* returns part names for all parts matching the criteria given in @a
|
||||||
|
* aQuery, into @a aResults. The query string is designed to be easily marshalled,
|
||||||
|
* i.e. serialized, so that long distance queries can be made with minimal overhead.
|
||||||
|
* The library source needs to have an intelligent friend on the other end if
|
||||||
|
* the actual library data is remotely located, otherwise it will be too slow
|
||||||
|
* to honor this portion of the API contract.
|
||||||
|
*
|
||||||
|
* @param aQuery is a string holding a domain specific language expression. One candidate
|
||||||
|
* here is an RPN s-expression that uses (and ..) and (or ..) operators. For example
|
||||||
|
* "(and (footprint 0805)(value 33ohm)(category passives))"
|
||||||
|
*/
|
||||||
|
STRINGS FindParts( const STRING& aQuery ) throw( IO_ERROR )
|
||||||
|
{
|
||||||
|
// run the query on the cached data first for any PARTS which are fully
|
||||||
|
// parsed (i.e. cached), then on the LIB_SOURCE to find any that
|
||||||
|
// are not fully parsed, then unify the results.
|
||||||
|
|
||||||
|
return STRINGS();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
STRING fetch; // scratch, used to fetch things, grows to worst case size.
|
||||||
|
STRINGS vfetch; // scratch, used to fetch things.
|
||||||
|
|
||||||
|
STRING name;
|
||||||
|
LIB_SOURCE* source;
|
||||||
|
LIB_SINK* sink;
|
||||||
|
STRING libraryURI;
|
||||||
|
|
||||||
|
STRINGS categories;
|
||||||
|
|
||||||
|
// PARTS parts;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace SCH
|
||||||
|
|
||||||
|
const STRING StrEmpty = "";
|
||||||
|
|
||||||
|
#endif // SCH_LIB_H_
|
||||||
|
|
Loading…
Reference in New Issue