Try to better my life as a programmer, starting with more comments and documentation

This commit is contained in:
Thomas Krijnen
2012-03-17 11:47:31 +00:00
parent cdbafac676
commit c31bc16dba
12 changed files with 81616 additions and 1021 deletions
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+71
View File
@@ -0,0 +1,71 @@
###############################################################################
# #
# This file is part of IfcOpenShell. #
# #
# IfcOpenShell is free software: you can redistribute it and/or modify #
# it under the terms of the Lesser GNU General Public License as published by #
# the Free Software Foundation, either version 3.0 of the License, or #
# (at your option) any later version. #
# #
# IfcOpenShell 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 #
# Lesser GNU General Public License for more details. #
# #
# You should have received a copy of the Lesser GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
###############################################################################
###############################################################################
# #
# This files uses the documentation files from buildingSMART to generate #
# descriptions from EXPRESS names that are suitable for comments in the C++ #
# code. The .csv files used by this file are generated from the MS Office #
# Access database, which in turn has been generated from the IFC baseline #
# documentation by the IFCDOC utility provided by buildingSMART. #
# #
###############################################################################
import re,csv
import csv
try: from html.entities import entitydefs
except: from htmlentitydefs import entitydefs
name_to_oid = {}
oid_to_desc = {}
oid_to_name = {}
oid_to_pid = {}
regices = list(zip([re.compile(s,re.M) for s in [r'<[\w\n=" \-/\.;_\t:%#,\?\(\)]+>',r'(\n[\t ]*){2,}',r'^[\t ]+','^']],['','\n\n',' ','/// ']))
definition_files = ['DocEntity.csv', 'DocEnumeration.csv', 'DocDefined.csv', 'DocSelect.csv']
for fn in definition_files:
with open(fn) as f:
for oid, name, desc in csv.reader(f, delimiter=';', quotechar='"'):
name_to_oid[name] = oid
oid_to_name[oid] = name
oid_to_desc[oid] = desc
with open('DocEntityAttributes.csv') as f:
for pid, x, oid in csv.reader(f, delimiter=';', quotechar='"'):
oid_to_pid[oid] = pid
with open('DocAttribute.csv') as f:
for oid, name, desc in csv.reader(f, delimiter=';', quotechar='"'):
pid = oid_to_pid[oid]
pname = oid_to_name[pid]
name_to_oid[(pname, name)] = oid
oid_to_desc[oid] = desc
def description(item):
global name_to_oid, oid_to_desc, oid_to_name, oid_to_pid
oid = name_to_oid.get(item,0)
desc = oid_to_desc.get(oid,None)
if desc:
for a,b in entitydefs.items(): desc = desc.replace("&%s;"%a,b)
desc = desc.replace("\r","")
for r,s in regices[:-1]: desc = r.sub(s,desc)
desc = desc.strip()
r,s = regices[-1]
desc = r.sub(s,desc)
return desc
+19 -8
View File
@@ -34,6 +34,8 @@ header = """
###############################################################################
import os, sys
import IfcDocumentation
filename = sys.argv[1]
#
@@ -160,12 +162,14 @@ class Typedef:
self.len = len(self.type)
elif isinstance(self.type,SelectType): selections.add(self.name)
simple_types.add(self.name)
comment = IfcDocumentation.description(self.name)
self.comment = comment+"\n" if comment else ''
def __str__(self):
global generator_mode
if generator_mode == 'HEADER' and isinstance(self.type,EnumType):
return ("namespace %(name)s {typedef %(type)s %(name)s;\nstd::string ToString(%(name)s v);\n%(name)s FromString(const std::string& s);}"%self.__dict__)%self.__dict__
return ("namespace %(name)s {\n%(comment)stypedef %(type)s %(name)s;\nstd::string ToString(%(name)s v);\n%(name)s FromString(const std::string& s);\n}"%self.__dict__)%self.__dict__
elif generator_mode == 'HEADER':
return "typedef %s %s;"%(self.type,self.name)
return "%stypedef %s %s;"%(self.comment,self.type,self.name)
elif generator_mode == 'SOURCE' and isinstance(self.type,EnumType):
generator_mode = 'SOURCE_TO'
s = "std::string %(name)s::ToString(%(name)s v) {\n if ( v < 0 || v >= %(len)d ) throw IfcException(\"Unable to find find keyword in schema\");\n const char* names[] = %(type)s;\n return names[v];\n}\n"%self.__dict__
@@ -185,7 +189,7 @@ class ArgumentList:
s = ""
argv = self.argstart
for a in self.l:
class_name = indent = ""
class_name = indent = comment = optional_comment = ""
return_type = str(a.type)
if generator_mode == 'SOURCE':
class_name = "%(class_name)s::"
@@ -204,13 +208,17 @@ class ArgumentList:
function_body2 = " { return !entity->getArgument(%d)->isNull(); }"%argv
else:
indent = " "
function_body = function_body2 = ";"
if a.optional: s += "\n%sbool %shas%s()%s"%(indent,class_name,a.name,function_body2)
function_body = function_body2 = ";"
comment = IfcDocumentation.description((self.class_name,a.name))
comment = comment+"\n" if comment else ''
comment = comment.replace("///","%s///"%indent)
optional_comment = "%s/// Whether the optional attribute %s is defined for this %s\n"%(indent,a.name,self.class_name)
if a.optional: s += "\n%s%sbool %shas%s()%s"%(optional_comment,indent,class_name,a.name,function_body2)
if ( str(a.type) in enumerations ):
return_type = "%(type)s::%(type)s"%a.__dict__
elif ( str(a.type) in entity_names ):
return_type = "%(type)s*"%a.__dict__
s += "\n%s%s %s%s()%s"%(indent,return_type,class_name,a.name,function_body)
s += "\n%s%s%s %s%s()%s"%(comment,indent,return_type,class_name,a.name,function_body)
argv += 1
return s
class InverseList:
@@ -228,12 +236,15 @@ class InverseList:
class Classdef:
def __init__(self,l):
self.class_name, self.parent_class, self.arguments, self.inverse = l
self.arguments.class_name = self.class_name
entity_names.add(self.class_name)
parent_relations[self.class_name] = self.parent_class
argument_count[self.class_name] = len(self.arguments)
def __str__(self):
if generator_mode == 'HEADER':
return "class %s : public %s {\npublic:%s%s%s\n};" % (self.class_name,
comment = IfcDocumentation.description(self.class_name)
comment = comment+"\n" if comment else ''
return "%sclass %s : public %s {\npublic:%s%s%s\n};" % (comment,self.class_name,
"IfcBaseClass" if self.parent_class is None else self.parent_class,
self.arguments,
self.inverse,
@@ -247,7 +258,7 @@ class Classdef:
)
elif generator_mode == 'SOURCE':
self.arguments.argstart = argument_start(self.class_name)
return (("\n// %(class_name)s"+str(self.arguments)+str(self.inverse)+
return (("\n// Function implementations for %(class_name)s"+str(self.arguments)+str(self.inverse)+
("\nbool %(class_name)s::is(Type::Enum v) const { return v == Type::%(class_name)s; }" if self.parent_class is None else
"\nbool %(class_name)s::is(Type::Enum v) const { return v == Type::%(class_name)s || %(parent_class)s::is(v); }")+
"\nType::Enum %(class_name)s::type() const { return Type::%(class_name)s; }"+
+653 -653
View File
File diff suppressed because it is too large Load Diff
+27376 -328
View File
File diff suppressed because one or more lines are too long
+13 -2
View File
@@ -33,7 +33,13 @@
const int BUF_SIZE = (128 * 1024 * 1024);
namespace IfcParse {
/// The File class represents a ISO 10303-21 IFC-SPF file in memory.
/// The file is interpreted as a sequence of tokens which are lazily
/// interpreted only when requested. If the size of the file is
/// larger than BUF_SIZE, the file is split into seperate pages, of
/// which only one is simultaneously kept in memory, for files
/// that define their entities not in a sequential nature, this is
/// detrimental for the performance of the parser.
class File {
private:
std::ifstream stream;
@@ -50,11 +56,16 @@ namespace IfcParse {
File(const std::string& fn);
File(std::istream& f, int len);
File(void* data, int len);
/// Returns the character at the cursor
char Peek();
/// Returns the character at specified offset
char Read(unsigned int offset);
void Inc();
/// Increment the file cursor and reads new page if necessary
void Inc();
void Close();
/// Moves the file cursor to an arbitrary offset in the file
void Seek(unsigned int offset);
/// Returns the cursor position
unsigned int Tell();
};
}
+43 -30
View File
@@ -52,24 +52,33 @@ namespace IfcParse {
typedef unsigned int Token;
//
// Provides functions to convert Tokens to binary data
// Tokens are merely offsets to where they can be read in the file
//
/// Provides functions to convert Tokens to binary data
/// Tokens are merely offsets to where they can be read in the file
class TokenFunc {
private:
static bool startsWith(Token t, char c);
public:
/// Returns the offset at which the token is read from the file
static unsigned int Offset(Token t);
/// Returns whether the token can be interpreted as a string
static bool isString(Token t);
/// Returns whether the token can be interpreted as an identifier
static bool isIdentifier(Token t);
/// Returns whether the token can be interpreted as an syntactical operator
static bool isOperator(Token t, char op = 0);
/// Returns whether the token can be interpreted as an enumerated value
static bool isEnumeration(Token t);
/// Returns whether the token can be interpreted as an datatype name
static bool isDatatype(Token t);
/// Returns the token interpreted as an integer
static int asInt(Token t);
/// Returns the token interpreted as an boolean (.T. or .F.)
static bool asBool(Token t);
/// Returns the token as a floating point number
static double asFloat(Token t);
/// Returns the token as a string (without the dot or apostrophe)
static std::string asString(Token t);
/// Returns a string representation of the token (including the dot or apostrophe)
static std::string toString(Token t);
};
@@ -81,9 +90,7 @@ namespace IfcParse {
Token TokenPtr(char c);
Token TokenPtr();
//
// Interprets a file as a sequential stream of Tokens
//
/// A stream of tokens to be read from a File.
class Tokens {
private:
File* file;
@@ -95,11 +102,9 @@ namespace IfcParse {
std::string TokenString(unsigned int offset);
};
//
// Argument of type list, e.g.
// #1=IfcDirection((1.,0.,0.));
// ==========
//
/// Argument of type list, e.g.
/// #1=IfcDirection((1.,0.,0.));
/// ==========
class ArgumentList: public Argument {
private:
std::vector<ArgumentPtr> list;
@@ -123,11 +128,9 @@ namespace IfcParse {
bool isNull() const;
};
//
// Argument of type scalar or string, e.g.
// #1=IfcVector(#2,1.0);
// == ===
//
/// Argument of type scalar or string, e.g.
/// #1=IfcVector(#2,1.0);
/// == ===
class TokenArgument : public Argument {
private:
@@ -150,11 +153,9 @@ namespace IfcParse {
bool isNull() const;
};
//
// Argument of an IFC type
// #1=IfcTrimmedCurve(#2,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(1.)),.T.,.PARAMETER.);
// ===================== =====================
//
/// Argument of an IFC simple type
/// #1=IfcTrimmedCurve(#2,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(1.)),.T.,.PARAMETER.);
/// ===================== =====================
class EntityArgument : public Argument {
private:
IfcUtil::IfcArgumentSelect* entity;
@@ -177,17 +178,17 @@ namespace IfcParse {
bool isNull() const;
};
//
// Entity defined in an IFC file, e.g.
// #1=IfcDirection((1.,0.,0.));
// ============================
//
/// Entity defined in an IFC file, e.g.
/// #1=IfcDirection((1.,0.,0.));
/// ============================
class Entity : public IfcAbstractEntity {
private:
ArgumentPtr args;
Ifc2x3::Type::Enum _type;
public:
/// The EXPRESS ENTITY_NAME
unsigned int _id;
/// The offset at which the entity is read
unsigned int offset;
Entity(unsigned int i, Tokens* t);
Entity(unsigned int i, Tokens* t, unsigned int o);
@@ -213,9 +214,8 @@ typedef std::map<std::string,Ifc2x3::IfcRoot::ptr> MapEntityByGuid;
typedef std::map<unsigned int,IfcEntities> MapEntitiesByRef;
typedef std::map<unsigned int,unsigned int> MapOffsetById;
//
// Several static convenience functions and variables
//
/// This class provides several static convenience functions and variables
/// and provide access to the entities in an IFC file
class Ifc {
private:
static MapEntityById byid;
@@ -228,12 +228,19 @@ private:
static std::ostream* log2;
static std::stringstream log_stream;
public:
/// Returns the first entity in the file, this probably is the entity with the lowest id (EXPRESS ENTITY_NAME)
static MapEntityById::const_iterator First();
/// Returns the last entity in the file, this probably is the entity with the highes id (EXPRESS ENTITY_NAME)
static MapEntityById::const_iterator Last();
/// Determines to what stream respectively progress and errors are logged
static void SetOutput(std::ostream* l1, std::ostream* l2);
/// Log a message to the output stream
static void LogMessage(const std::string& type, const std::string& message, const IfcAbstractEntityPtr entity=0);
static IfcParse::File* file;
static IfcParse::Tokens* tokens;
/// Returns all entities in the file that match the template argument.
/// NOTE: This also returns subtypes of the requested type, for example:
/// IfcWall will also return IfcWallStandardCase entities
template <class T>
static typename T::list EntitiesByType() {
IfcEntities e = EntitiesByType(T::Class());
@@ -244,9 +251,15 @@ public:
}
return l;
}
/// Returns all entities in the file that match the positional argument.
/// NOTE: This also returns subtypes of the requested type, for example:
/// IfcWall will also return IfcWallStandardCase entities
static IfcEntities EntitiesByType(Ifc2x3::Type::Enum t);
/// Returns all entities in the file that reference the id
static IfcEntities EntitiesByReference(int id);
/// Returns the entity with the specified id
static IfcEntity EntityById(int id);
/// Returns the entity with the specified GlobalId
static Ifc2x3::IfcRoot::ptr Ifc::EntityByGuid(const std::string& guid);
static bool Init(const std::string& fn);
static bool Init(std::istream& fn, int len);