Add initial files

This commit is contained in:
Marty Kraimer
2010-08-10 12:43:47 -04:00
parent d08cd9a4c5
commit 81f3a1a0b2
17 changed files with 594 additions and 0 deletions

17
Makefile Normal file
View File

@@ -0,0 +1,17 @@
#Makefile at top of application tree
TOP = .
include $(TOP)/configure/CONFIG
DIRS := $(DIRS) $(filter-out $(DIRS), configure)
DIRS := $(DIRS) $(filter-out $(DIRS), $(wildcard *App))
DIRS := $(DIRS) $(filter-out $(DIRS), $(wildcard iocBoot))
define DIR_template
$(1)_DEPEND_DIRS = configure
endef
$(foreach dir, $(filter-out configure,$(DIRS)),$(eval $(call DIR_template,$(dir))))
iocBoot_DEPEND_DIRS += $(filter %App,$(DIRS))
include $(TOP)/configure/RULES_TOP

107
README.html Normal file
View File

@@ -0,0 +1,107 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>EPICS pvData C++</title>
</head>
<body>
<h1 style="text-align: center">EPICS pvData C++<br />
Overview<br />
2010.08.02</h1>
CONTENTS
<hr />
<h2 style="text-align: center">Introduction</h2>
<hr />
<p>This project has the begining of the C++ implementation of pvData. The
following is done:</p>
<dl>
<dt>introspection interfaces</dt>
<dd>The introspection interfaces for clients are described.</dd>
<dt>introspection implementation</dt>
<dd>The following have been implemented: Type, ScalarType, Field,
Scalar</dd>
<dt>test</dt>
<dd>A test of Scalar.</dd>
<dt>As mentioned below there are major problems with the current
implementation.</dt>
</dl>
<p>Since the last version the following are the main changes:</p>
<ul>
<li>The name space no longer has the trailing " namespace pvData {" </li>
<li>A typedef has been added to define a StringConst and all string
arguments are now a StringConst. See gargage collection below for
details.</li>
<li>typedefs have been added for FieldPtr, ScalarPtr, etc. These make the
boost stuff somewhat transparent.</li>
<li>The array arguments have been changed from using * to using [].</li>
<li>Other arguments were change to be more understandable.</li>
<li>All the toString methods were changed from something like:
<pre> static const std::string toString(...</pre>
to
<pre>static void toString(std::string &amp;buf,</pre>
This should be more efficent.</li>
</ul>
<hr />
<h2 style="text-align: center">Building</h2>
<hr />
<p>The project is structured as an epics base client application. Edit
configure/RELEASE so that it references your EPICS base and then just
type:</p>
<pre> make</pre>
<p>At the top. Then execute the test in the bin directory.</p>
<p>pvDataApp has the following sub directories:</p>
<dl>
<dt>pv</dt>
<dd>pvData.h has the interface descriptions for client code.</dd>
<dt>factory</dt>
<dd>FieldCreateFactory.cpp has the current implementation</dd>
<dt>test</dt>
<dd>Has a test for the current implementation.</dd>
</dl>
<hr />
<h2 style="text-align: center">Questions about Classes</h2>
<hr />
<p>The pure virtual classes defined in pvData.h now work. But there are still
some things that are not so nice. Amoung these are:</p>
<ul>
<li>User code sees pointers instead of references. Can this be changed
while keeping the boost::shared_ptr support?</li>
<li>The toString methods have an argument of "std::string &amp;buf" instead
of "std::string *". But in the test code I could not create a
"std::string &amp;" to work. I do not know why.</li>
<li>Can arguments and return descriptions be defined better?</li>
<li>Is const present everywhere it should be? Remember that introspection
classes are immutable and are shared whereever possible.</li>
<li>The code is NOT thread safe. When we decide for sure what thread/lock
support to choose I will fix this.</li>
</ul>
<p>HELP WILL BE GREATLY APPRECIATED. because I am still coming up to speed
with c++</p>
<hr />
<h2 style="text-align: center">Garbage Collection</h2>
<hr />
<p>boost::shared_ptr is currenly used for implementations of Field, Scalar,
etc. It is also used for all string arguments passed to methods. Since string
values are freely shared by pvData, pvAccess, etc, this is really important.
questions:</p>
<ol>
<li>Is the implementation using shared_ptr correctly?</li>
<li>Should other things currently defined use stared_ptr?</li>
</ol>
</body>
</html>

30
configure/CONFIG Normal file
View File

@@ -0,0 +1,30 @@
# CONFIG
# You might want to change this to some shared set of rules, e.g.
# RULES=/path/to/epics/support/modules/rules/x-y
RULES=$(EPICS_BASE)
include $(TOP)/configure/RELEASE
-include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH)
-include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH).Common
ifdef T_A
-include $(TOP)/configure/RELEASE.Common.$(T_A)
-include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH).$(T_A)
endif
CONFIG=$(RULES)/configure
include $(CONFIG)/CONFIG
# Override for definition in base
INSTALL_LOCATION = $(TOP)
include $(TOP)/configure/CONFIG_SITE
-include $(TOP)/configure/CONFIG_SITE.$(EPICS_HOST_ARCH)
-include $(TOP)/configure/CONFIG_SITE.$(EPICS_HOST_ARCH).Common
ifdef T_A
-include $(TOP)/configure/CONFIG_SITE.Common.$(T_A)
-include $(TOP)/configure/CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A)
-include $(TOP)/configure/O.$(T_A)/CONFIG_APP_INCLUDE
endif

26
configure/CONFIG_SITE Normal file
View File

@@ -0,0 +1,26 @@
# CONFIG_SITE
# Make any application-specific changes to the EPICS build
# configuration variables in this file.
#
# Host/target specific settings can be specified in files named
# CONFIG_SITE.$(EPICS_HOST_ARCH).Common
# CONFIG_SITE.Common.$(T_A)
# CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A)
# Set this when you only want to compile this application
# for a subset of the cross-compiled target architectures
# that Base is built for.
#CROSS_COMPILER_TARGET_ARCHS = vxWorks-68040
# Set this when your IOC and the host use different paths
# to access the application. This will be needed to boot
# from a Microsoft FTP server or with some NFS mounts.
# You must rebuild in the iocBoot directory for this to
# take effect.
#IOCS_APPL_TOP = <path to application top as seen by IOC>
# If you don't want to install into $(TOP) then
# define INSTALL_LOCATION here
#INSTALL_LOCATION=<fullpathname>

17
configure/Makefile Normal file
View File

@@ -0,0 +1,17 @@
TOP=..
include $(TOP)/configure/CONFIG
# CHECK_RELEASE controls the consistency checking of the support
# applications defined in the $(TOP)/configure/RELEASE* files.
# Normally CHECK_RELEASE should be set to YES.
# Set CHECK_RELEASE to NO to disable checking completely.
# Set CHECK_RELEASE to WARN to perform consistency checking,
# but continue the build even if conflicts are found.
CHECK_RELEASE = YES
TARGETS = $(CONFIG_TARGETS)
CONFIGS += $(subst ../,,$(wildcard $(CONFIG_INSTALLS)))
include $(TOP)/configure/RULES

30
configure/RELEASE Normal file
View File

@@ -0,0 +1,30 @@
#RELEASE Location of external products
#
# IF YOU MAKE ANY CHANGES to this file you MUST at least run
# "gnumake" in this directory afterwards; you usually need
# to run "gnumake rebuild" in the application's top level
# directory each time this file is changed.
#
# NOTE: The build does not check dependencies against files
# that are outside this application, thus you should run
# "gnumake distclean install" in the top directory each time
# EPICS_BASE, SNCSEQ, or any other external module defined
# in the RELEASE file is rebuilt.
#
# Host/target specific settings can be specified in files named
# RELEASE.$(EPICS_HOST_ARCH).Common
# RELEASE.Common.$(T_A)
# RELEASE.$(EPICS_HOST_ARCH).$(T_A)
TEMPLATE_TOP=$(EPICS_BASE)/templates/makeBaseApp/top
#If using the sequencer, point SNCSEQ at its top directory:
#SNCSEQ=$(EPICS_BASE)/../modules/soft/seq
# EPICS_BASE usually appears last so other apps can override stuff:
EPICS_BASE=/home/install/epics/base
#Capfast users may need the following definitions
#CAPFAST_TEMPLATES=
#SCH2EDIF_PATH=

6
configure/RULES Normal file
View File

@@ -0,0 +1,6 @@
# RULES
include $(CONFIG)/RULES
# Library should be rebuilt because LIBOBJS may have changed.
$(LIBNAME): ../Makefile

2
configure/RULES.ioc Normal file
View File

@@ -0,0 +1,2 @@
#RULES.ioc
include $(CONFIG)/RULES.ioc

2
configure/RULES_DIRS Normal file
View File

@@ -0,0 +1,2 @@
#RULES_DIRS
include $(CONFIG)/RULES_DIRS

3
configure/RULES_TOP Normal file
View File

@@ -0,0 +1,3 @@
#RULES_TOP
include $(CONFIG)/RULES_TOP

7
pvDataApp/Makefile Normal file
View File

@@ -0,0 +1,7 @@
TOP = ..
include $(TOP)/configure/CONFIG
DIRS += pv
DIRS += factory
DIRS += test
include $(TOP)/configure/RULES_DIRS

View File

@@ -0,0 +1,176 @@
#include <cstddef>
#include <cstdlib>
#include <string>
#include <cstdio>
#include <boost/smart_ptr.hpp>
#include "pvData.h"
namespace epics { namespace pvData {
void TypeFunc::toString(std::string &buf,const Type type) {
static const std::string unknownString = "logic error unknown Type";
switch(type) {
case scalar : buf += "scalar"; break;
case scalarArray : buf += "scalarArray"; break;
case structure : buf += "structure"; break;
case structureArray : buf += "structureArray"; break;
default:
throw std::invalid_argument(unknownString);
}
}
bool ScalarTypeFunc::isInteger(ScalarType type) {
if(type>=pvByte && type<=pvLong) return true;
return false;
}
bool ScalarTypeFunc::isNumeric(ScalarType type) {
if(type>=pvByte && type<=pvDouble) return true;
return false;
}
bool ScalarTypeFunc::isPrimitive(ScalarType type) {
if(type>=pvBoolean && type<=pvDouble) return true;
return false;
}
ScalarType ScalarTypeFunc::getScalarType(std::string const& pvalue) {
static const std::string unknownString = "error unknown ScalarType";
if(pvalue.compare("boolean")==0) return pvBoolean;
if(pvalue.compare("byte")==0) return pvByte;
if(pvalue.compare("short")==0) return pvShort;
if(pvalue.compare("int")==0) return pvInt;
if(pvalue.compare("long")==0) return pvLong;
if(pvalue.compare("float")==0) return pvFloat;
if(pvalue.compare("double")==0) return pvDouble;
if(pvalue.compare("string")==0) return pvString;
throw std::invalid_argument(unknownString);
}
void ScalarTypeFunc::toString(std::string &buf,const ScalarType scalarType) {
static const std::string unknownString = "logic error unknown ScalarType";
switch(scalarType) {
case pvBoolean : buf += "pvBoolean"; return;
case pvByte : buf += "pvByte"; return;;
case pvShort : buf += "pvShort"; return;
case pvInt : buf += "pvInt"; return;
case pvLong : buf += "pvLong"; return;
case pvFloat : buf += "pvFloat"; return;
case pvDouble : buf += "pvDouble"; return;
case pvString : buf += "pvString"; return;
}
throw std::invalid_argument(unknownString);
}
Field::~Field(){}
class BaseField : public Field {
public:
BaseField(std::string const& fieldName,Type type);
~BaseField();
virtual std::string const& getFieldName() const;
virtual Type getType() const;
virtual void toString(std::string &buf) const;
virtual void toString(std::string &buf,int indentLevel) const;
private:
std::string const fieldName;
Type type;
};
BaseField::~BaseField() {
delete(&fieldName);
}
BaseField::BaseField(std::string const& fieldName,Type type)
:fieldName(fieldName),type(type){}
std::string const& BaseField::getFieldName() const {return fieldName;}
Type BaseField::getType() const {return type;}
void BaseField::toString(std::string &buf) const{toString(buf,0);}
void BaseField::toString(std::string &buffer,int indentLevel) const{
for(int i=0; i<indentLevel; i++) buffer += " ";
buffer += "field ";
buffer += fieldName.c_str();
buffer += " type ";
TypeFunc::toString(buffer,type);
}
Scalar::~Scalar(){}
class BaseScalar: public BaseField,public Scalar {
public:
BaseScalar(std::string const& fieldName,ScalarType scalarType);
~BaseScalar();
// WHY DO I HAVE TO DESCRIBE AND DEFINE THESE??
virtual std::string const& getFieldName() const;
virtual Type getType() const;
virtual ScalarType getScalarType() const { return scalarType;}
virtual void toString(std::string &buf) const;
virtual void toString(std::string &buf,int indentLevel) const;
private:
ScalarType scalarType;
};
BaseScalar::BaseScalar(std::string const& fieldName,ScalarType scalarType)
: BaseField(fieldName,scalar),scalarType(scalarType){}
BaseScalar::~BaseScalar() {}
std::string const& BaseScalar::getFieldName() const
{
return BaseField::getFieldName();
}
Type BaseScalar::getType() const
{
return BaseField::getType();
}
void BaseScalar::toString(std::string &buf) const{toString(buf,0);}
void BaseScalar::toString(std::string &buffer,int indentLevel) const{
BaseField::toString(buffer,indentLevel);
buffer += " scalarType ";
ScalarTypeFunc::toString(buffer,scalarType);
}
static std::string notImplemented = "not implemented";
FieldCreate::FieldCreate(){};
Field const & FieldCreate::create(std::string const& fieldName, Field const & field) const
{
throw std::invalid_argument(notImplemented);
}
Scalar const & FieldCreate::createScalar(std::string const& fieldName,ScalarType scalarType) const
{
BaseScalar *baseScalar = new BaseScalar(fieldName,scalarType);
return *baseScalar;
}
ScalarArray const & FieldCreate::createScalarArray(std::string const& fieldName,ScalarType elementType) const
{
throw std::invalid_argument(notImplemented);
}
Structure const & FieldCreate::createStructure (std::string const& fieldName,Field const * const fields) const
{
throw std::invalid_argument(notImplemented);
}
StructureArray const & FieldCreate::createStructureArray(std::string const& fieldName,Structure const & structure) const
{
throw std::invalid_argument(notImplemented);
}
static FieldCreate* instance = 0;
class FieldCreateExt : public FieldCreate {
public:
FieldCreateExt(): FieldCreate(){};
};
FieldCreate & getFieldCreate() {
if(instance==0) instance = new FieldCreateExt();
return *instance;
}
}}

View File

@@ -0,0 +1,12 @@
TOP=../..
include $(TOP)/configure/CONFIG
LIBSRCS += FieldCreateFactory.cpp
LIBRARY=pvFactory
include $(TOP)/configure/RULES
#----------------------------------------
# ADD RULES AFTER THIS LINE

10
pvDataApp/pv/Makefile Normal file
View File

@@ -0,0 +1,10 @@
TOP=../..
include $(TOP)/configure/CONFIG
INC += pvData.h
include $(TOP)/configure/RULES
#----------------------------------------
# ADD RULES AFTER THIS LINE

97
pvDataApp/pv/pvData.h Normal file
View File

@@ -0,0 +1,97 @@
/* pvData.h */
#include <string>
#include <stdexcept>
#ifndef TYPE_H
#define TYPE_H
namespace epics { namespace pvData {
enum Type {
scalar,
scalarArray,
structure,
structureArray
};
class TypeFunc {
public:
static void toString(std::string &buf,const Type type);
};
enum ScalarType {
pvBoolean,
pvByte,
pvShort,
pvInt,
pvLong,
pvFloat,
pvDouble,
pvString
};
class ScalarTypeFunc {
public:
static bool isInteger(ScalarType type);
static bool isNumeric(ScalarType type);
static bool isPrimitive(ScalarType type);
static ScalarType getScalarType(std::string const& value);
static void toString(std::string &buf,const ScalarType scalarType);
};
class Field {
public:
virtual ~Field();
virtual std::string const& getFieldName() const = 0;
virtual Type getType() const = 0;
virtual void toString(std::string &buf) const = 0;
virtual void toString(std::string &buf,int indentLevel) const = 0;
};
class Field;
class Scalar;
class ScalarArray;
class Structure;
class StructureArray;
class Scalar : public Field{
public:
virtual ~Scalar();
virtual ScalarType getScalarType() const = 0;
};
class ScalarArray : public Field{
public:
virtual ~ScalarArray();
virtual ScalarType getScalerType() const = 0;
};
class Structure : public Field {
public:
virtual ~Structure();
virtual std::string const * const getFieldNames() const = 0;
virtual Field const & getField(std::string const& fieldName) const = 0;
virtual int getFieldIndex(std::string const& fieldName) const = 0;
virtual Field const * const getFields() const = 0;
};
class StructureArray : public Field{
public:
virtual ~StructureArray();
virtual Structure const & getStructure() const = 0;
};
class FieldCreate {
public:
Field const & create(std::string const& fieldName,Field const & field) const;
Scalar const & createScalar(std::string const& fieldName,ScalarType scalarType) const;
ScalarArray const & createScalarArray(std::string const& fieldName,ScalarType elementType) const;
Structure const & createStructure (std::string const& fieldName,Field const * const fields) const;
StructureArray const & createStructureArray(std::string const& fieldName,Structure const & structure) const;
protected:
FieldCreate();
};
extern FieldCreate & getFieldCreate();
}}
#endif /* TYPE_H */

14
pvDataApp/test/Makefile Normal file
View File

@@ -0,0 +1,14 @@
TOP=../..
include $(TOP)/configure/CONFIG
PROD_HOST = test
test_SRCS += test.cpp
test_LIBS += pvFactory
include $(TOP)/configure/RULES
#----------------------------------------
# ADD RULES AFTER THIS LINE

38
pvDataApp/test/test.cpp Normal file
View File

@@ -0,0 +1,38 @@
/* pvDataMain.cpp */
/* Author: Marty Kraimer Date: 17MAR2000 */
#include <stddef.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <stdio.h>
#include "pvData.h"
using namespace epics::pvData;
int main(int argc,char *argv[])
{
Type type = scalar;
ScalarType scalarType = pvDouble;
bool value = ScalarTypeFunc::isNumeric(scalarType);
printf("isNumeric %s\n",(value ? "true" : "false"));
std::string* myString= new std::string("type ");
TypeFunc::toString(*myString,type);
*myString += " scalarType ";
ScalarTypeFunc::toString(*myString,scalarType);
printf("%s\n",myString->c_str());
FieldCreate &fieldCreate = getFieldCreate();
std::string valueName("value");
Scalar const & scalar = fieldCreate.createScalar(valueName,scalarType);
type = scalar.getType();
myString->clear();
*myString += "type ";
TypeFunc::toString(*myString,type);
printf("%s\n",myString->c_str());
myString->clear();
scalar.toString(*myString);
printf("%s\n",myString->c_str());
return(0);
}