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:
+
+ - User code sees pointers instead of references. Can this be changed
+ while keeping the boost::shared_ptr support?
+ - The toString methods have an argument of "std::string &buf" instead
+ of "std::string *". But in the test code I could not create a
+ "std::string &" to work. I do not know why.
+ - Can arguments and return descriptions be defined better?
+ - Is const present everywhere it should be? Remember that introspection
+ classes are immutable and are shared whereever possible.
+ - The code is NOT thread safe. When we decide for sure what thread/lock
+ support to choose I will fix this.
+
+
+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:
+
+ - Is the implementation using shared_ptr correctly?
+ - Should other things currently defined use stared_ptr?
+
+
+
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);
+}