diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..f0d9ad7 --- /dev/null +++ b/Makefile @@ -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 + + diff --git a/README.html b/README.html new file mode 100644 index 0000000..e83279b --- /dev/null +++ b/README.html @@ -0,0 +1,107 @@ + + + + + + EPICS pvData C++ + + + +

EPICS pvData C++
+Overview
+2010.08.02

+CONTENTS +
+ +

Introduction

+
+ +

This project has the begining of the C++ implementation of pvData. The +following is done:

+
+
introspection interfaces
+
The introspection interfaces for clients are described.
+
introspection implementation
+
The following have been implemented: Type, ScalarType, Field, + Scalar
+
test
+
A test of Scalar.
+
As mentioned below there are major problems with the current + implementation.
+
+ +

Since the last version the following are the main changes:

+ +
+ +

Building

+
+ +

The project is structured as an epics base client application. Edit +configure/RELEASE so that it references your EPICS base and then just +type:

+
   make
+ +

At the top. Then execute the test in the bin directory.

+ +

pvDataApp has the following sub directories:

+
+
pv
+
pvData.h has the interface descriptions for client code.
+
factory
+
FieldCreateFactory.cpp has the current implementation
+
test
+
Has a test for the current implementation.
+
+
+ +

Questions about Classes

+
+ +

The pure virtual classes defined in pvData.h now work. But there are still +some things that are not so nice. Amoung these are:

+ + +

HELP WILL BE GREATLY APPRECIATED. because I am still coming up to speed +with c++

+
+ +

Garbage Collection

+
+ +

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:

+
    +
  1. Is the implementation using shared_ptr correctly?
  2. +
  3. Should other things currently defined use stared_ptr?
  4. +
+ + diff --git a/configure/CONFIG b/configure/CONFIG new file mode 100644 index 0000000..ae1e38d --- /dev/null +++ b/configure/CONFIG @@ -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 + diff --git a/configure/CONFIG_SITE b/configure/CONFIG_SITE new file mode 100644 index 0000000..0a13fc6 --- /dev/null +++ b/configure/CONFIG_SITE @@ -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 = + +# If you don't want to install into $(TOP) then +# define INSTALL_LOCATION here +#INSTALL_LOCATION= + diff --git a/configure/Makefile b/configure/Makefile new file mode 100644 index 0000000..ade29a7 --- /dev/null +++ b/configure/Makefile @@ -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 + diff --git a/configure/RELEASE b/configure/RELEASE new file mode 100644 index 0000000..37d8c6d --- /dev/null +++ b/configure/RELEASE @@ -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= + diff --git a/configure/RULES b/configure/RULES new file mode 100644 index 0000000..6d56e14 --- /dev/null +++ b/configure/RULES @@ -0,0 +1,6 @@ +# RULES + +include $(CONFIG)/RULES + +# Library should be rebuilt because LIBOBJS may have changed. +$(LIBNAME): ../Makefile diff --git a/configure/RULES.ioc b/configure/RULES.ioc new file mode 100644 index 0000000..901987c --- /dev/null +++ b/configure/RULES.ioc @@ -0,0 +1,2 @@ +#RULES.ioc +include $(CONFIG)/RULES.ioc diff --git a/configure/RULES_DIRS b/configure/RULES_DIRS new file mode 100644 index 0000000..3ba269d --- /dev/null +++ b/configure/RULES_DIRS @@ -0,0 +1,2 @@ +#RULES_DIRS +include $(CONFIG)/RULES_DIRS diff --git a/configure/RULES_TOP b/configure/RULES_TOP new file mode 100644 index 0000000..d09d668 --- /dev/null +++ b/configure/RULES_TOP @@ -0,0 +1,3 @@ +#RULES_TOP +include $(CONFIG)/RULES_TOP + diff --git a/pvDataApp/Makefile b/pvDataApp/Makefile new file mode 100644 index 0000000..237ac33 --- /dev/null +++ b/pvDataApp/Makefile @@ -0,0 +1,7 @@ +TOP = .. +include $(TOP)/configure/CONFIG +DIRS += pv +DIRS += factory +DIRS += test +include $(TOP)/configure/RULES_DIRS + diff --git a/pvDataApp/factory/FieldCreateFactory.cpp b/pvDataApp/factory/FieldCreateFactory.cpp new file mode 100644 index 0000000..802cec5 --- /dev/null +++ b/pvDataApp/factory/FieldCreateFactory.cpp @@ -0,0 +1,176 @@ + +#include +#include +#include +#include + +#include + +#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 +#include +#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 */ diff --git a/pvDataApp/test/Makefile b/pvDataApp/test/Makefile new file mode 100644 index 0000000..86fe7af --- /dev/null +++ b/pvDataApp/test/Makefile @@ -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 + diff --git a/pvDataApp/test/test.cpp b/pvDataApp/test/test.cpp new file mode 100644 index 0000000..ff0fe63 --- /dev/null +++ b/pvDataApp/test/test.cpp @@ -0,0 +1,38 @@ +/* pvDataMain.cpp */ +/* Author: Marty Kraimer Date: 17MAR2000 */ + +#include +#include +#include +#include +#include + +#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); +}