Commit c4a6b418 authored by Dick Hollenbeck's avatar Dick Hollenbeck

++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.
parents 78ef3152 80f21358
...@@ -4,6 +4,13 @@ KiCad ChangeLog 2010 ...@@ -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:
......
/*
* 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 @@ ...@@ -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, ...@@ -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 @@ ...@@ -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: ...@@ -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: ...@@ -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.
......
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} )
This diff is collapsed.
/*
* 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
/*
* 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_
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment