lestarch: fixing fpp+cmake for latest release/v3.0.0

This commit is contained in:
M Starch 2021-08-11 20:22:21 -07:00
commit ef28ed5be6
284 changed files with 2303 additions and 2135 deletions

View File

@ -1,4 +1,6 @@
.git
.github
.dockerignore
**.mdxml
**/docs
**build

View File

@ -10,4 +10,3 @@ USER fprime
# Code file to execute when the docker container starts up (`entrypoint.sh`)
ENTRYPOINT ["/entrypoint.sh"]

View File

@ -4,9 +4,10 @@
set -e
set -x
cd "$GITHUB_WORKSPACE"
if [ "$GITHUB_WORKFLOW" != "Autodocs" ]
if [ "$GITHUB_WORKFLOW" == "Autodocs" ]
then
"$GITHUB_WORKSPACE/ci/master.bash" QUICK
else
/autodoc.bash
else
#echo "$INPUT_TEST1"
"$GITHUB_WORKSPACE/ci/master.bash" $INPUT_TEST
fi

View File

@ -1,5 +1,12 @@
name: 'F prime CI'
description: 'Runs continuous integration testing on F prime'
inputs:
test:
description: Test number to run
required: true
default: ''
runs:
using: 'docker'
image: 'Dockerfile'
args:
- ${{ inputs.test }}

View File

@ -1,13 +1,10 @@
ignore$
/html/
(?:^|/)(?i)COPYRIGHT
(?:^|/)(?i)LICEN[CS]E
(?:^|/)vendor/
^\.github/
^Autocoders/Python/test/.*\.xml$
/doc/xml/
/html/
/third-party/
\.min\.
ignore$
\.bak$
\.bin$
\.dat$
@ -23,6 +20,7 @@ ignore$
\.md5$
\.mdxml$
\.mdzip$
\.min\.
\.otf$
\.pdf$
\.png$
@ -39,3 +37,9 @@ ignore$
\.xls$
\.xlsx$
\.xsd$
^Autocoders/Python/test/.*\.xml$
^Autocoders/Python/test/param1/test/ut/Tester\.hpp$
^config/PolyDbImplCfg\.hpp$
^config/PrmDbImplTesterCfg\.hpp$
^RPI/settings\.ini$
^\.github/

View File

@ -67,7 +67,6 @@ arijitdas
arinc
arity
arpa
ASerialize
asm
aspx
ASTRING
@ -112,7 +111,6 @@ batchmode
bbd
bc
bcm
BDRV
BDV
bfree
bibtex
@ -130,11 +128,11 @@ bodychars
bodytext
bools
boolt
bootlin
bootup
brc
bre
bsd
BSerialize
bslash
buf
BUFFERALLOCATE
@ -215,7 +213,6 @@ CMDREG
cmds
CMDSEQ
cmp
cn
cnt
cntx
cobj
@ -241,7 +238,6 @@ config
configparser
configurability
configurator
Connectedoutput
cooldown
coor
coravy
@ -398,13 +394,11 @@ DSTUBBED
DSYNC
DTGT
dtor
DUCKCOMP
Duerschmid
duey
dumparch
dumpobj
DVI
Dvr
DWN
dylib
EACCES
@ -447,7 +441,6 @@ endl
endloc
endswith
enduml
enewcommand
ENOENT
ENOSPC
ENOTDIR
@ -481,7 +474,6 @@ EVENTID
eventname
evr
evt
ewcommand
EXAMPLECOMPONENTIMPL
excinfo
exe
@ -503,6 +495,7 @@ fd
fdset
featuredarticles
FEEDNAME
ffff
fflush
Ffs
fgetc
@ -541,7 +534,7 @@ formatline
foundin
fpconfighpp
FPGA
FPL
fpl
fpp
fppi
FPport
@ -555,6 +548,7 @@ fputil
frontend
frox
frsize
fsanitize
fscanf
fstream
fstrength
@ -587,7 +581,6 @@ getcwd
getdata
getdefaultencoding
getenv
getexample
getextern
gethostbyname
gethostname
@ -733,7 +726,6 @@ inode
inorder
INPCK
Inputline
INPUTPORT
installable
INSTALLDIR
instanceof
@ -892,7 +884,6 @@ LTIMER
LTLT
LVL
lxml
lxr
MACROFILE
magicdraw
mailto
@ -1006,6 +997,7 @@ ncsl
NDELAY
ndiffs
netdb
Netscape
Netscape's
newloc
newroot
@ -1024,7 +1016,6 @@ noargport
NOCOLOR
NOCTTY
nogen
noinclude
nolog
nomagic
nonblock
@ -1042,6 +1033,7 @@ nostdlib
notask
notchars
NOTFOUND
nothrow
NOTYPE
Nowicki
npm
@ -1052,8 +1044,6 @@ NSPACES
nukenewlines
nullptr
numargs
Numinput
Numoutput
nums
nxt
objclass
@ -1066,6 +1056,7 @@ odo
oflag
okidocki
oldeol
OMG
OMG's
onchange
onlinepubs
@ -1112,7 +1103,6 @@ params
PARENB
PARODD
parseable
PARTITIONHUBCOMP
PASSIVEC
pathmaker
pbuild
@ -1147,7 +1137,6 @@ pollpri
POLYDB
POLYDBCOMP
POLYDBIMPL
POLYDBIMPLCFG
popd
popen
portlist
@ -1177,7 +1166,6 @@ prm
PRMDB
PRMDBIMPL
PRMDBIMPLTESTER
PRMDBIMPLTESTERCFG
PRMDBLIMPLCFG
prmname
probs
@ -1248,7 +1236,6 @@ RBF
Rce
RCHILD
rcs
Rcv
rcvd
RCVTIMEO
RDONLY
@ -1275,6 +1262,7 @@ relaxng
relpath
REMOVEDIRECTORY
REMOVEFILE
renewcommand
reparse
reserializing
resname
@ -1338,7 +1326,6 @@ searchdata
SEARCHENGINE
segfault
sendfile
sendline
SENDPARTIAL
sendto
seqgen
@ -1359,7 +1346,6 @@ SETLOGGING
setname
setop
setopt
setoutput
setprotocol
setquaternion
setresult
@ -1781,6 +1767,7 @@ XPath
xsh
Xss
Xvfb
xxxx
XYZZY
yacc
yacgen

View File

@ -1,3 +1,5 @@
# See https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples:-patterns
# data urls
"data:[^"]*"
'data:[^']*'
@ -23,8 +25,9 @@ xmi:id="[^"]*"
# uuid:
\b[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}\b
# https://www.gnu.org/software/groff/manual/groff.html
# man troff content
\\f[BCIP]
\\f[BCIPR]
\&#x[AD];
value="(?:[0-9a-f]{1,2} )*"
@ -43,3 +46,6 @@ value="(?:[0-9a-f]{1,2} )*"
# Tar archive items
\b(?:\\n|)tar(?:\s+-[a-zA-Z]+|\s[a-z]+)+
# slashes after spaces are not in paths
LaTeX \\.* \\

10
.github/actions/tutorial/Dockerfile vendored Normal file
View File

@ -0,0 +1,10 @@
FROM nasafprime/fprime-base
USER root
RUN apt-get update && apt-get install -y --no-install-recommends doxygen && \
apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* && pip3 --no-cache-dir install fprime-tools fprime-gds
COPY gps-build /gps-build
ENTRYPOINT ["/gps-build"]

View File

@ -0,0 +1,5 @@
name: 'F prime tutorial check'
description: 'Runs community tutorial support on F prime'
runs:
using: 'docker'
image: 'Dockerfile'

15
.github/actions/tutorial/gps-build vendored Executable file
View File

@ -0,0 +1,15 @@
#!/bin/bash
# Exit when any command fails
set -e
set -x
# Change to GitHub workspace
cd "$GITHUB_WORKSPACE"
# Move to GpsApp directory
cd gps-tutorial/GpsApp
# Build GpsApp
fprime-util generate
fprime-util build

View File

@ -12,8 +12,8 @@ on:
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
build:
# This workflow contains 4 jobs. One for every CI test."
Framework:
# The type of runner that the job will run on
runs-on: ubuntu-latest
@ -25,11 +25,82 @@ jobs:
- name: F prime CI step
uses: ./.github/actions/
id: github-ci-action
with:
test: Framework
# Archive the outputs
- name: 'Archive Logs'
uses: actions/upload-artifact@v2
if: always()
with:
name: ci-logs
name: ci-framework-logs
path: ci-logs.tar.gz
retention-days: 5
Ref:
# The type of runner that the job will run on
runs-on: ubuntu-latest
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v2
# Runs the CI action internal to the repository
- name: F prime CI step
uses: ./.github/actions/
id: github-ci-action
with:
test: 'Ref'
# Archive the outputs
- name: 'Archive Logs'
uses: actions/upload-artifact@v2
if: always()
with:
name: ci-ref-logs
path: ci-logs.tar.gz
retention-days: 5
RPI:
# The type of runner that the job will run on
runs-on: ubuntu-latest
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v2
# Runs the CI action internal to the repository
- name: F prime CI step
uses: ./.github/actions/
id: github-ci-action
with:
test: 'RPI'
# Archive the outputs
- name: 'Archive Logs'
uses: actions/upload-artifact@v2
if: always()
with:
name: ci-rpi-logs
path: ci-logs.tar.gz
retention-days: 5
Integration:
# The type of runner that the job will run on
runs-on: ubuntu-latest
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v2
# Runs the CI action internal to the repository
- name: F prime CI step
uses: ./.github/actions/
id: github-ci-action
with:
test: '30-ints'
# Archive the outputs
- name: 'Archive Logs'
uses: actions/upload-artifact@v2
if: always()
with:
name: ci-int-logs
path: ci-logs.tar.gz
retention-days: 5

View File

@ -13,19 +13,19 @@ on:
types: ['opened', 'reopened', 'synchronize']
jobs:
build:
spelling:
name: Spell checking
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
steps:
- name: checkout-merge
if: "contains(github.event_name, 'pull_request')"
uses: actions/checkout@v2.0.0
uses: actions/checkout@v2
with:
ref: refs/pull/${{github.event.pull_request.number}}/merge
fetch-depth: 5
- name: checkout
if: "!contains(github.event_name, 'pull_request')"
uses: actions/checkout@v2.0.0
if: ${{ github.event_name == 'push' }}
uses: actions/checkout@v2
- uses: check-spelling/check-spelling@v0.0.19
id: spelling
with:
fetch-depth: 5
- uses: check-spelling/check-spelling@0.0.17-alpha
shortest_word: 2

37
.github/workflows/tutorial-support.yml vendored Normal file
View File

@ -0,0 +1,37 @@
# This is a basic workflow to help you get started with Actions
name: tutorial-support
# Controls when the action will run.
on:
# Triggers the workflow on push or pull request events but only for the devel branch
push:
branches: [ master, devel ]
pull_request:
branches: [ master ]
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
build:
# The type of runner that the job will run on
runs-on: ubuntu-latest
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
- name: checkout latest GpsApp repo
uses: actions/checkout@v2
with:
repository: fprime-community/gps-tutorial
path: ./gps-tutorial
# Checks-out latest version of the fprime repo
- name: checkout latest fprime repo
uses: actions/checkout@v2
with:
path: ./gps-tutorial/fprime
# Build tutorial test
- name: tutorial-test
uses: ./gps-tutorial/fprime/.github/actions/tutorial/
id: github-tutorial-action

View File

@ -8,18 +8,19 @@
path_classifiers:
test:
- "/Gds/test"
- "/Fw/Python/test"
docs:
- "/docs"
- docs
queries:
# Not excluding any results right now because we want to be alerted for all issues and fixes
# In the future we may exclude depreciated code like ptf/ and Gds/src/wxgui/
# - exclude:
- include: cpp/incorrect-not-operator-usage
- include:
tags:
- "correctness"
- include:
tags:
- "reliability"
extraction:
cpp:
prepare:
prepare:
packages:
- "python3"
- "python3-pip"
@ -27,12 +28,12 @@ extraction:
after_prepare:
# setup the venv and install packages
- "python3 -m venv ./fprime-venv"
- ". ./fprime-venv/bin/activate"
- ". ./fprime-venv/bin/activate"
- "pip install fprime-tools fprime-gds"
configure:
configure:
command:
before_index:
- "fprime-util generate"
index:
index:
build_command:
- "fprime-util build --all"

View File

@ -115,7 +115,7 @@ def pinit():
current_dir = os.getcwd()
usage = "usage: %prog [options] [xml_filename]"
vers = "%prog " + VERSION.id + " " + VERSION.comment
vers = f"%prog {VERSION.id} {VERSION.comment}"
parser = OptionParser(usage, version=vers)
@ -133,7 +133,7 @@ def pinit():
"--path",
dest="work_path",
type="string",
help="Switch to new working directory (def: %s)." % current_dir,
help=f"Switch to new working directory (def: {current_dir}).",
action="store",
default=current_dir,
)
@ -299,7 +299,7 @@ def pinit():
def generate_topology(the_parsed_topology_xml, xml_filename, opt):
DEBUG.debug("Topology xml type description file: %s" % xml_filename)
DEBUG.debug(f"Topology xml type description file: {xml_filename}")
generator = TopoFactory.TopoFactory.getInstance()
if not (opt.default_topology_dict or opt.xml_topology_dict):
generator.set_generate_ID(False)
@ -363,9 +363,7 @@ def generate_topology(the_parsed_topology_xml, xml_filename, opt):
# comp.set_component_object(comp.)
else:
PRINT.info(
"Components with type {} aren't in the topology model.".format(
comp.get_type()
)
f"Components with type {comp.get_type()} aren't in the topology model."
)
# Hack to set up deployment path for instanced dictionaries (if one exists remove old one)
@ -378,26 +376,23 @@ def generate_topology(the_parsed_topology_xml, xml_filename, opt):
break
else:
raise FileNotFoundError(
"{} not found in any of: {}".format(DEPLOYMENT, get_build_roots())
f"{DEPLOYMENT} not found in any of: {get_build_roots()}"
)
dict_dir = os.environ["DICT_DIR"]
PRINT.info("Removing old instanced topology dictionaries in: %s", dict_dir)
PRINT.info(f"Removing old instanced topology dictionaries in: {dict_dir}")
import shutil
if os.path.exists(dict_dir):
shutil.rmtree(dict_dir)
PRINT.info(
"Overriding for instanced topology dictionaries the --dict_dir option with xml derived path: %s",
dict_dir,
f"Overriding for instanced topology dictionaries the --dict_dir option with xml derived path: {dict_dir}"
)
#
xml_list = []
for parsed_xml_type in parsed_xml_dict:
if parsed_xml_dict[parsed_xml_type] is None:
PRINT.info(
"XML of type {} is being used, but has not been parsed correctly. Check if file exists or add xml file with the 'import_component_type' tag to the Topology file.".format(
parsed_xml_type
)
f"XML of type {parsed_xml_type} is being used, but has not been parsed correctly. Check if file exists or add xml file with the 'import_component_type' tag to the Topology file."
)
raise Exception()
xml_list.append(parsed_xml_dict[parsed_xml_type])
@ -419,12 +414,9 @@ def generate_topology(the_parsed_topology_xml, xml_filename, opt):
comp_type = comp.get_type()
comp_name = comp.get_name()
comp_id = int(comp.get_base_id(), 0)
PRINT.debug(
"Processing {} [{}] ({})".format(comp_name, comp_type, hex(comp_id))
)
PRINT.debug(f"Processing {comp_name} [{comp_type}] ({hex(comp_id)})")
top_dict_gen.set_current_comp(comp)
top_dict_gen.check_for_enum_xml()
top_dict_gen.check_for_serial_xml()
top_dict_gen.check_for_commands()
@ -446,7 +438,7 @@ def generate_topology(the_parsed_topology_xml, xml_filename, opt):
fileName = the_parsed_topology_xml.get_xml_filename().replace(
"Ai.xml", "Dictionary.xml"
)
PRINT.info("Generating XML dictionary %s" % fileName)
PRINT.info(f"Generating XML dictionary {fileName}")
fd = open(
fileName, "wb"
) # Note: binary forces the same encoding of the source files
@ -514,8 +506,7 @@ def generate_component_instance_dictionary(
# can't have external non-xml members
if len(xml_parser_obj.get_include_header_files()):
PRINT.info(
"ERROR: Component include serializables cannot use user-defined types. file: %s"
% serializable_file
f"ERROR: Component include serializables cannot use user-defined types. file: {serializable_file}"
)
sys.exit(-1)
@ -535,7 +526,7 @@ def generate_component_instance_dictionary(
"Commands", "InstanceCommandVisitor", True, True
)
for command_model in component_model.get_commands():
DEBUG.info("Processing command %s" % command_model.get_mnemonic())
DEBUG.info(f"Processing command {command_model.get_mnemonic()}")
defaultStartCmd = default_dict_generator.create("InstanceDictStart")
defaultCmdHeader = default_dict_generator.create("InstanceDictHeader")
defaultCmdBody = default_dict_generator.create("InstanceDictBody")
@ -545,7 +536,7 @@ def generate_component_instance_dictionary(
defaultCmdBody(command_model, topology_model)
for parameter_model in component_model.get_parameters():
DEBUG.info("Processing parameter %s" % parameter_model.get_name())
DEBUG.info(f"Processing parameter {parameter_model.get_name()}")
defaultStartCmd = default_dict_generator.create("InstanceDictStart")
defaultCmdHeader = default_dict_generator.create("InstanceDictHeader")
defaultCmdBody = default_dict_generator.create("InstanceDictBody")
@ -560,7 +551,7 @@ def generate_component_instance_dictionary(
"Events", "InstanceEventVisitor", True, True
)
for event_model in component_model.get_events():
DEBUG.info("Processing event %s" % event_model.get_name())
DEBUG.info(f"Processing event {event_model.get_name()}")
defaultStartEvent = default_dict_generator.create("InstanceDictStart")
defaultEventHeader = default_dict_generator.create("InstanceDictHeader")
defaultEventBody = default_dict_generator.create("InstanceDictBody")
@ -575,7 +566,7 @@ def generate_component_instance_dictionary(
"Channels", "InstanceChannelVisitor", True, True
)
for channel_model in component_model.get_channels():
DEBUG.info("Processing channel %s" % channel_model.get_name())
DEBUG.info(f"Processing channel {channel_model.get_name()}")
defaultStartChannel = default_dict_generator.create("InstanceDictStart")
defaultChannelHeader = default_dict_generator.create("InstanceDictHeader")
defaultChannelBody = default_dict_generator.create("InstanceDictBody")
@ -594,7 +585,7 @@ def generate_component(
"""
parsed_port_xml_list = []
if opt.gen_report:
report_file = open("%sReport.txt" % xml_filename.replace("Ai.xml", ""), "w")
report_file = open(f"{xml_filename.replace('Ai.xml', '')}Report.txt", "w")
num_input_ports = 0
num_output_ports = 0
@ -607,9 +598,9 @@ def generate_component(
num_output_ports = num_output_ports + int(port.get_max_number())
if len(the_parsed_component_xml.get_ports()):
if num_input_ports:
report_file.write("Input Ports: %d\n" % num_input_ports)
report_file.write(f"Input Ports: {num_input_ports}\n")
if num_output_ports:
report_file.write("Output Ports: %d\n" % num_output_ports)
report_file.write(f"Output Ports: {num_output_ports}\n")
# Count regular commands
commands = 0
@ -631,7 +622,7 @@ def generate_component(
idList += opcode + ","
if commands > 0:
report_file.write("Commands: %d\n OpCodes: %s\n" % (commands, idList[:-1]))
report_file.write(f"Commands: {commands}\n OpCodes: {idList[:-1]}\n")
if len(the_parsed_component_xml.get_channels()):
idList = ""
@ -640,7 +631,7 @@ def generate_component(
channels += len(channel.get_ids())
for id in channel.get_ids():
idList += id + ","
report_file.write("Channels: %d\n ChanIds: %s\n" % (channels, idList[:-1]))
report_file.write(f"Channels: {channels}\n ChanIds: {idList[:-1]}\n")
if len(the_parsed_component_xml.get_events()):
idList = ""
@ -649,7 +640,7 @@ def generate_component(
events += len(event.get_ids())
for id in event.get_ids():
idList += id + ","
report_file.write("Events: %d\n EventIds: %s\n" % (events, idList[:-1]))
report_file.write(f"Events: {events}\n EventIds: {idList[:-1]}\n")
if len(the_parsed_component_xml.get_parameters()):
idList = ""
@ -658,9 +649,7 @@ def generate_component(
parameters += len(parameter.get_ids())
for id in parameter.get_ids():
idList += id + ","
report_file.write(
"Parameters: %d\n ParamIds: %s\n" % (parameters, idList[:-1])
)
report_file.write(f"Parameters: {parameters}\n ParamIds: {idList[:-1]}\n")
#
# Configure the meta-model for the component
#
@ -689,8 +678,7 @@ def generate_component(
# can't have external non-xml members
if len(xml_parser_obj.get_include_header_files()):
PRINT.info(
"ERROR: Component include serializables cannot use user-defined types. file: %s"
% serializable_file
f"ERROR: Component include serializables cannot use user-defined types. file: {serializable_file}"
)
sys.exit(-1)
@ -835,7 +823,7 @@ def generate_component(
"Commands", "CommandVisitor", True, True
)
for command_model in component_model.get_commands():
DEBUG.info("Processing command %s" % command_model.get_mnemonic())
DEBUG.info(f"Processing command {command_model.get_mnemonic()}")
defaultStartCmd = default_dict_generator.create("DictStart")
defaultCmdHeader = default_dict_generator.create("DictHeader")
defaultCmdBody = default_dict_generator.create("DictBody")
@ -845,7 +833,7 @@ def generate_component(
defaultCmdBody(command_model)
for parameter_model in component_model.get_parameters():
DEBUG.info("Processing parameter %s" % parameter_model.get_name())
DEBUG.info(f"Processing parameter {parameter_model.get_name()}")
defaultStartCmd = default_dict_generator.create("DictStart")
defaultCmdHeader = default_dict_generator.create("DictHeader")
defaultCmdBody = default_dict_generator.create("DictBody")
@ -858,7 +846,7 @@ def generate_component(
# iterate through command instances
default_dict_generator.configureVisitor("Events", "EventVisitor", True, True)
for event_model in component_model.get_events():
DEBUG.info("Processing event %s" % event_model.get_name())
DEBUG.info(f"Processing event {event_model.get_name()}")
defaultStartEvent = default_dict_generator.create("DictStart")
defaultEventHeader = default_dict_generator.create("DictHeader")
defaultEventBody = default_dict_generator.create("DictBody")
@ -873,7 +861,7 @@ def generate_component(
"Channels", "ChannelVisitor", True, True
)
for channel_model in component_model.get_channels():
DEBUG.info("Processing channel %s" % channel_model.get_name())
DEBUG.info(f"Processing channel {channel_model.get_name()}")
defaultStartChannel = default_dict_generator.create("DictStart")
defaultChannelHeader = default_dict_generator.create("DictHeader")
defaultChannelBody = default_dict_generator.create("DictBody")
@ -923,7 +911,7 @@ def generate_port(the_parsed_port_xml, port_file):
#
# Configure the meta-model for the component
#
DEBUG.debug("Port xml type description file: %s" % port_file)
DEBUG.debug(f"Port xml type description file: {port_file}")
generator = PortFactory.PortFactory.getInstance()
port_model = generator.create(the_parsed_port_xml)
#
@ -933,12 +921,12 @@ def generate_port(the_parsed_port_xml, port_file):
#
# Configure file names and each visitor here.
#
type = the_parsed_port_xml.get_interface().get_name()
the_type = the_parsed_port_xml.get_interface().get_name()
#
# Configure each visitor here.
#
if "Ai" in port_file:
base = type
base = the_type
h_instance_name = base + "_H"
cpp_instance_name = base + "_Cpp"
else:
@ -1000,7 +988,7 @@ def generate_serializable(the_serial_xml, opt):
# Configure the meta-model for the serializable here
#
f = the_serial_xml.get_xml_filename()
DEBUG.debug("Serializable xml type description file: %s" % f)
DEBUG.debug(f"Serializable xml type description file: {f}")
n = the_serial_xml.get_name()
ns = the_serial_xml.get_namespace()
c = the_serial_xml.get_comment()
@ -1031,7 +1019,7 @@ def generate_serializable(the_serial_xml, opt):
# only generate if serializable is usable for dictionary. Can't have includes of other types
if opt.default_dict:
if len(i) != 0 or len(i2) != 0:
PRINT.info("Dictionary: Skipping %s because of external includes" % (f))
PRINT.info(f"Dictionary: Skipping {f} because of external includes")
else:
# borrow source visitor pattern for serializable dictionary
if opt.dict_dir is None:
@ -1042,7 +1030,7 @@ def generate_serializable(the_serial_xml, opt):
if opt.default_topology_dict:
if len(i) != 0 or len(i2) != 0:
PRINT.info("Dictionary: Skipping %s because of external includes" % (f))
PRINT.info(f"Dictionary: Skipping {f} because of external includes")
else:
# borrow source visitor pattern for serializable dictionary
if opt.dict_dir is None:
@ -1099,12 +1087,12 @@ def generate_serializable(the_serial_xml, opt):
finishSource(model)
def generate_dependency_file(filename, target_file, subst_path, parser, type):
def generate_dependency_file(filename, target_file, subst_path, parser, the_type):
# verify directory exists for dependency file and is directory
if not os.path.isdir(os.path.dirname(filename)):
PRINT.info(
"ERROR: Dependency file path %s does not exist!", os.path.dirname(filename)
f"ERROR: Dependency file path {os.path.dirname(filename)} does not exist!"
)
sys.exit(-1)
@ -1126,18 +1114,18 @@ def generate_dependency_file(filename, target_file, subst_path, parser, type):
# print("sub: %s\ndep_file: %s\ntdir: %s\ntfile: %s\nfp: %s"%(subst_path_local,filename,target_directory,target_file_local,full_path))
# write target to file
dep_file.write("%s:" % full_path)
dep_file.write(f"{full_path}:")
# assemble list of files
if type == "interface":
if the_type == "interface":
file_list = (
parser.get_include_header_files()
+ parser.get_includes_serial_files()
+ parser.get_include_enum_files()
+ parser.get_include_array_files()
)
elif type == "component":
elif the_type == "component":
file_list = (
parser.get_port_type_files()
+ parser.get_header_files()
@ -1146,14 +1134,14 @@ def generate_dependency_file(filename, target_file, subst_path, parser, type):
+ parser.get_enum_type_files()
+ parser.get_array_type_files()
)
elif type == "serializable":
elif the_type == "serializable":
file_list = (
parser.get_include_header_files()
+ parser.get_includes()
+ parser.get_include_enums()
+ parser.get_include_arrays()
)
elif type == "assembly" or type == "deployment":
elif the_type == "assembly" or the_type == "deployment":
# get list of dependency files from XML/header file list
file_list_tmp = list(parser.get_comp_type_file_header_dict().keys())
file_list = file_list_tmp
@ -1161,7 +1149,7 @@ def generate_dependency_file(filename, target_file, subst_path, parser, type):
# for f in file_list_tmp:
# file_list.append(f.replace("Ai.xml","Ac.hpp"))
else:
PRINT.info("ERROR: Unrecognized dependency type %s!", type)
PRINT.info(f"ERROR: Unrecognized dependency type {the_type}!")
sys.exit(-1)
# write dependencies
@ -1175,7 +1163,7 @@ def generate_dependency_file(filename, target_file, subst_path, parser, type):
)
sys.exit(-1)
dep_file.write("\\\n %s " % full_path)
dep_file.write(f"\\\n {full_path} ")
# carriage return
dep_file.write("\n\n")
@ -1205,7 +1193,7 @@ def main():
# specifies an alternate working directory.
if os.path.exists(opt.work_path) == False:
Parser.error("Specified path does not exist (%s)!" % opt.work_path)
Parser.error(f"Specified path does not exist ({opt.work_path})!")
working_dir = opt.work_path
@ -1243,7 +1231,7 @@ def main():
# Parse the input Component XML file and create internal meta-model
#
if len(args) == 0:
PRINT.info("Usage: %s [options] xml_filename" % sys.argv[0])
PRINT.info(f"Usage: {sys.argv[0]} [options] xml_filename")
return
else:
xml_filenames = args[0:]
@ -1300,7 +1288,7 @@ def main():
if EnumGenerator.generate_enum(xml_filename):
ERROR = False
PRINT.info(
"Completed generating files for %s Enum XML...." % xml_filename
f"Completed generating files for {xml_filename} Enum XML...."
)
else:
ERROR = True
@ -1311,7 +1299,7 @@ def main():
if ArrayGenerator.generate_array(xml_filename):
ERROR = False
PRINT.info(
"Completed generating files for %s Array XML..." % xml_filename
f"Completed generating files for {xml_filename} Array XML..."
)
else:
ERROR = True

View File

@ -3,7 +3,7 @@
xmlns="http://purl.oclc.org/dsdl/schematron">
<pattern id="ASYNC_PORT">
<rule context="component">
<assert test="(//component/@kind = 'active' and (count(//component/ports/port/@kind[. = 'async_input']) + count(//component/internal_interfaces/internal_interface) ) >= 1) or not (//component/@kind = 'active')">
<assert test="(//component/@kind = 'active' and (count(//component/ports/port/@kind[. = 'async_input']) + count(//component/commands/command/@kind[. = 'async']) + count(//component/internal_interfaces/internal_interface) ) >= 1) or not (//component/@kind = 'active')">
Active components should have at least 1 port of kind async_input or internal_interface.
</assert>
</rule>

View File

@ -37,6 +37,14 @@
</optional>
<optional>
<attribute name = "serialize_type">
<a:documentation>Serialization type of the enum.</a:documentation>
<text/>
</attribute>
</optional>
<!-- Elements -->
<interleave>
<optional>

View File

@ -114,8 +114,19 @@
</attribute>
</optional>
<!-- Type, size, and internal enum define are defined within this ref -->
<ref name="type_size_choice_define"/>
<!-- Optional element -->
<interleave>
<optional>
<a:documentation>Optional default value.</a:documentation>
<element name="default">
<text/>
</element>
</optional>
<!-- Type, size, and internal enum define are defined within this ref -->
<ref name="type_size_choice_define"/>
</interleave>
</element>
</define>
</grammar>

View File

@ -24,6 +24,7 @@
\#include <stdio.h>
\#include "Fw/Types/Assert.hpp"
\#include <Fw/Types/StringUtils.hpp>
\#include "${name}ArrayAc.hpp"
@ -34,66 +35,47 @@ namespace ${namespace} {
#if $type == "string":
${name}::${name}String::${name}String(const char* src): StringBase() {
this->copyBuff(src,this->getCapacity());
Fw::StringUtils::string_copy(this->m_buf, src, sizeof(this->m_buf));
}
${name}::${name}String::${name}String(const Fw::StringBase& src): StringBase() {
this->copyBuff(src.toChar(),this->getCapacity());
Fw::StringUtils::string_copy(this->m_buf, src.toChar(), sizeof(this->m_buf));
}
${name}::${name}String::${name}String(const ${name}String& src): StringBase() {
this->copyBuff(src.toChar(),this->getCapacity());
Fw::StringUtils::string_copy(this->m_buf, src.toChar(), sizeof(this->m_buf));
}
${name}::${name}String::${name}String(): StringBase() {
this->m_buf[0] = 0;
}
${name}::${name}String& ${name}::${name}String::operator=(const ${name}String& other) {
Fw::StringUtils::string_copy(this->m_buf, other.toChar(), sizeof(this->m_buf));
return *this;
}
${name}::${name}String& ${name}::${name}String::operator=(const StringBase& other) {
Fw::StringUtils::string_copy(this->m_buf, other.toChar(), sizeof(this->m_buf));
return *this;
}
${name}::${name}String& ${name}::${name}String::operator=(const char* other) {
Fw::StringUtils::string_copy(this->m_buf, other, sizeof(this->m_buf));
return *this;
}
${name}::${name}String::~${name}String() {
}
bool ${name}::${name}String::operator==(const ${name}String& src) const {
return (0 == strncmp(this->m_buf,src.m_buf,sizeof(this->m_buf)));
}
NATIVE_UINT_TYPE ${name}::${name}String::length() const {
return (NATIVE_UINT_TYPE)strnlen(this->m_buf,sizeof(this->m_buf));
}
const char* ${name}::${name}String::toChar() const {
return this->m_buf;
}
Fw::SerializeStatus ${name}::${name}String::serialize(Fw::SerializeBufferBase& buffer) const {
NATIVE_UINT_TYPE strSize = strnlen(this->m_buf,sizeof(this->m_buf));
// serialize string
return buffer.serialize((U8*)this->m_buf,strSize);
}
Fw::SerializeStatus ${name}::${name}String::deserialize(Fw::SerializeBufferBase& buffer) {
NATIVE_UINT_TYPE maxSize = sizeof(this->m_buf);
// deserialize string
Fw::SerializeStatus stat = buffer.deserialize((U8*)this->m_buf,maxSize);
// make sure it is null-terminated
this->terminate(maxSize);
return stat;
}
NATIVE_UINT_TYPE ${name}::${name}String::getCapacity() const {
return sizeof(this->m_buf);
}
void ${name}::${name}String::terminate(NATIVE_UINT_TYPE size) {
// null terminate the string
this->m_buf[size < sizeof(this->m_buf)?size:sizeof(this->m_buf)-1] = 0;
}
const ${name}::${name}String& ${name}::${name}String::operator=(const ${name}::${name}String& other) {
this->copyBuff(other.m_buf,this->getCapacity());
return *this;
}
#end if
// ----------------------------------------------------------------------
@ -249,7 +231,7 @@ void ${name}::toString(Fw::StringBase& text) const {
#if $typeinfo == "extern":
// Need to instantiate toString for arrays and serializable types
#for $index in $range(0, $size):
Fw::EightyCharString str${index};
Fw::String str${index};
this->elements[$index].toString(str${index});
#end for
#end if
@ -281,7 +263,7 @@ void ${name}::toString(Fw::StringBase& text) const {
\#ifdef BUILD_UT
std::ostream& operator<<(std::ostream& os, const ${name}& obj) {
Fw::EightyCharString temp;
Fw::String temp;
obj.toString(temp);
os << temp;

View File

@ -24,7 +24,7 @@
\#ifndef ${namespace}_${name}_HPP
\#define ${namespace}_${name}_HPP
\#include "Fw/Types/EightyCharString.hpp"
\#include "Fw/Types/String.hpp"
\#include "Fw/Types/BasicTypes.hpp"
\#include "Fw/Types/Serializable.hpp"
#for $t in $include_headers:
@ -62,22 +62,17 @@ namespace ${namespace} {
${name}String(const Fw::StringBase& src); //!< string base constructor
${name}String(const ${name}String& src); //!< string base constructor
${name}String(); //!< default constructor
virtual ~${name}String(); //!< destructor
${name}String& operator=(const ${name}String& other); //!< assignment operator
${name}String& operator=(const Fw::StringBase& other); //!< other string assignment operator
${name}String& operator=(const char* other); //!< char* assignment operator
~${name}String(); //!< destructor
const char* toChar() const; //!< retrieves char buffer of string
NATIVE_UINT_TYPE length() const; //!< returns length of string
bool operator==(const ${name}String& src) const; //!< equality operator
const ${name}String& operator=(const ${name}String& other); //!< equal operator for other strings
Fw::SerializeStatus serialize(Fw::SerializeBufferBase& buffer) const; //!< serialization function
Fw::SerializeStatus deserialize(Fw::SerializeBufferBase& buffer); //!< deserialization function
NATIVE_UINT_TYPE getCapacity() const;
private:
NATIVE_UINT_TYPE getCapacity() const ;
void terminate(NATIVE_UINT_TYPE size); //!< terminate the string
char m_buf[${string_size}]; //!< buffer for string storage
};
#end if

View File

@ -15,7 +15,7 @@
\#include <${comp_include_path}/${include_name}ComponentAc.hpp>
\#include <Fw/Types/Assert.hpp>
\#if FW_ENABLE_TEXT_LOGGING
\#include <Fw/Types/EightyCharString.hpp>
\#include <Fw/Types/String.hpp>
\#endif
#set $class_name = $name + "ComponentBase"
@ -1310,7 +1310,7 @@ namespace ${namespace} {
#for $arg_name, $arg_type, $comment, $size, $typeinfo in $args:
#if not ($is_primitive_type($arg_type) or ($typeinfo == "enum") or ($typeinfo == "string")) :
Fw::EightyCharString ${arg_name}Str;
Fw::String ${arg_name}Str;
${arg_name}.toString(${arg_name}Str);
#end if
#end for

View File

@ -152,14 +152,22 @@ a == $item_value#slurp
Fw::SerializeStatus ${name} :: serialize(Fw::SerializeBufferBase& buffer) const
{
Fw::SerializeStatus status;
#if $serialize_type
status = buffer.serialize(static_cast<${serialize_type}>(this->e));
#else
status = buffer.serialize(static_cast<FwEnumStoreType>(this->e));
#end if
return status;
}
Fw::SerializeStatus ${name} :: deserialize(Fw::SerializeBufferBase& buffer)
{
Fw::SerializeStatus status;
#if $serialize_type
${serialize_type} es;
#else
FwEnumStoreType es;
#end if
status = buffer.deserialize(es);
if (status == Fw::FW_SERIALIZE_OK)
this->e = static_cast<t>(es);

View File

@ -24,7 +24,7 @@
\#ifndef ${namespace}_${name}_HPP
\#define ${namespace}_${name}_HPP
\#include "Fw/Types/EightyCharString.hpp"
\#include "Fw/Types/String.hpp"
\#include "Fw/Types/BasicTypes.hpp"
\#include "Fw/Types/Serializable.hpp"
@ -66,7 +66,11 @@ namespace ${namespace} {
// ----------------------------------------------------------------------
enum {
#if $serialize_type
SERIALIZED_SIZE = sizeof(${serialize_type})
#else
SERIALIZED_SIZE = sizeof(FwEnumStoreType)
#end if
};
//! Number of items in ${name} enum

View File

@ -1,4 +1,4 @@
/// Input $name port description
/// Output $name port description
/// $desc
class Output${name}Port : public Fw::OutputPortBase {

View File

@ -1,5 +1,6 @@
\#include <FpConfig.hpp>
\#include <Fw/Types/Assert.hpp>
\#include <Fw/Types/Serializable.hpp>
\#include <Fw/Types/StringUtils.hpp>
\#include <${port_include_path}/${include_file}>

View File

@ -8,62 +8,47 @@ namespace ${n} {
#if $type == "string":
${argname}String::${argname}String(const char* src): StringBase() {
this->copyBuff(src,this->getCapacity());
Fw::StringUtils::string_copy(this->m_buf, src, sizeof(this->m_buf));
}
${argname}String::${argname}String(const Fw::StringBase& src): StringBase() {
this->copyBuff(src.toChar(),this->getCapacity());
Fw::StringUtils::string_copy(this->m_buf, src.toChar(), sizeof(this->m_buf));
}
${argname}String::${argname}String(const ${argname}String& src): StringBase() {
this->copyBuff(src.toChar(),this->getCapacity());
Fw::StringUtils::string_copy(this->m_buf, src.toChar(), sizeof(this->m_buf));
}
${argname}String::${argname}String(): StringBase() {
this->m_buf[0] = 0;
}
${argname}String::~${argname}String() {
${argname}String& ${argname}String::operator=(const ${argname}String& other) {
Fw::StringUtils::string_copy(this->m_buf, other.toChar(), sizeof(this->m_buf));
return *this;
}
NATIVE_UINT_TYPE ${argname}String::length() const {
return (NATIVE_UINT_TYPE)strnlen(this->m_buf,sizeof(this->m_buf));
${argname}String& ${argname}String::operator=(const StringBase& other) {
Fw::StringUtils::string_copy(this->m_buf, other.toChar(), sizeof(this->m_buf));
return *this;
}
${argname}String& ${argname}String::operator=(const char* other) {
Fw::StringUtils::string_copy(this->m_buf, other, sizeof(this->m_buf));
return *this;
}
${argname}String::~${argname}String() {
}
const char* ${argname}String::toChar() const {
return this->m_buf;
}
Fw::SerializeStatus ${argname}String::serialize(Fw::SerializeBufferBase& buffer) const {
NATIVE_UINT_TYPE strSize = strnlen(this->m_buf,sizeof(this->m_buf));
// serialize string as buffer
return buffer.serialize((U8*)this->m_buf,strSize);
}
Fw::SerializeStatus ${argname}String::deserialize(Fw::SerializeBufferBase& buffer) {
NATIVE_UINT_TYPE maxSize = sizeof(this->m_buf);
// deserialize string
Fw::SerializeStatus stat = buffer.deserialize((U8*)this->m_buf,maxSize);
// make sure it is null-terminated
this->terminate(maxSize);
return stat;
}
NATIVE_UINT_TYPE ${argname}String::getCapacity() const {
return sizeof(this->m_buf);
}
const ${argname}String& ${argname}String::operator=(const ${argname}String& other) {
this->copyBuff(other.m_buf,this->getCapacity());
return *this;
}
void ${argname}String::terminate(NATIVE_UINT_TYPE size) {
// null terminate the string
this->m_buf[size < sizeof(this->m_buf)?size:sizeof(this->m_buf)-1] = 0;
}
#end if
#if $type == "buffer":
@ -107,20 +92,30 @@ namespace ${n} {
public:
NATIVE_UINT_TYPE getBuffCapacity() const {
return sizeof(m_buff);
return Input${name}Port::SERIALIZED_SIZE;
}
U8* getBuffAddr() {
#if len($arg_list) > 0:
return m_buff;
#else
return nullptr;
#end if
}
const U8* getBuffAddr() const {
#if len($arg_list) > 0:
return m_buff;
#else
return nullptr;
#end if
}
private:
#if len($arg_list) > 0:
U8 m_buff[Input${name}Port::SERIALIZED_SIZE];
#end if
};

View File

@ -33,18 +33,15 @@ namespace ${namespace} {
${argname}String(const Fw::StringBase& src); //!< other string constructor
${argname}String(const ${argname}String& src); //!< same type string constructor
${argname}String(); //!< default constructor
virtual ~${argname}String(); //!< destructor
${argname}String& operator=(const ${argname}String& other); //!< assignment operator
${argname}String& operator=(const Fw::StringBase& other); //!< other string assignment operator
${argname}String& operator=(const char* other); //!< char* assignment operator
~${argname}String(); //!< destructor
const char* toChar() const; //!< return internal buffer
NATIVE_UINT_TYPE length() const; //!< length of string
const ${argname}String& operator=(const ${argname}String& other); //!< equal operator for other strings
Fw::SerializeStatus serialize(Fw::SerializeBufferBase& buffer) const; //!< deserialization method
Fw::SerializeStatus deserialize(Fw::SerializeBufferBase& buffer); //!< serialization method
NATIVE_UINT_TYPE getCapacity() const;
private:
NATIVE_UINT_TYPE getCapacity() const ;
void terminate(NATIVE_UINT_TYPE size); //!< terminate the string
char m_buf[${size}]; //!< buffer for string
};

View File

@ -1,7 +1,8 @@
\#include <${include_path}/${namespace}${name}SerializableAc.hpp>
\#include <Fw/Types/Assert.hpp>
\#include <Fw/Types/BasicTypes.hpp>
\#include <Fw/Types/StringUtils.hpp>
\#if FW_SERIALIZABLE_TO_STRING
\#include <Fw/Types/EightyCharString.hpp>
\#include <Fw/Types/String.hpp>
\#endif
\#include <cstring>

View File

@ -5,6 +5,6 @@
\#include <stdio.h> // snprintf
\#ifdef BUILD_UT
\#include <iostream>
\#include <Fw/Types/EightyCharString.hpp>
\#include <Fw/Types/String.hpp>
\#endif
\#endif

View File

@ -3,69 +3,50 @@
namespace ${n} {
#end for
#end if
#for ($memname,$type,$size,$format,$comment) in $mem_list:
#for ($memname,$type,$size,$format,$comment,$default) in $mem_list:
#if $type == "string":
${name}::${memname}String::${memname}String(const char* src): StringBase() {
this->copyBuff(src,this->getCapacity());
Fw::StringUtils::string_copy(this->m_buf, src, sizeof(this->m_buf));
}
${name}::${memname}String::${memname}String(const Fw::StringBase& src): StringBase() {
this->copyBuff(src.toChar(),this->getCapacity());
Fw::StringUtils::string_copy(this->m_buf, src.toChar(), sizeof(this->m_buf));
}
${name}::${memname}String::${memname}String(const ${memname}String& src): StringBase() {
this->copyBuff(src.toChar(),this->getCapacity());
Fw::StringUtils::string_copy(this->m_buf, src.toChar(), sizeof(this->m_buf));
}
${name}::${memname}String::${memname}String(): StringBase() {
this->m_buf[0] = 0;
}
${name}::${memname}String& ${name}::${memname}String::operator=(const ${memname}String& other) {
Fw::StringUtils::string_copy(this->m_buf, other.toChar(), sizeof(this->m_buf));
return *this;
}
${name}::${memname}String& ${name}::${memname}String::operator=(const StringBase& other) {
Fw::StringUtils::string_copy(this->m_buf, other.toChar(), sizeof(this->m_buf));
return *this;
}
${name}::${memname}String& ${name}::${memname}String::operator=(const char* other) {
Fw::StringUtils::string_copy(this->m_buf, other, sizeof(this->m_buf));
return *this;
}
${name}::${memname}String::~${memname}String() {
}
bool ${name}::${memname}String::operator==(const ${memname}String& src) const {
return (0 == strncmp(this->m_buf,src.m_buf,sizeof(this->m_buf)));
}
NATIVE_UINT_TYPE ${name}::${memname}String::length() const {
return (NATIVE_UINT_TYPE)strnlen(this->m_buf,sizeof(this->m_buf));
}
const char* ${name}::${memname}String::toChar() const {
return this->m_buf;
}
Fw::SerializeStatus ${name}::${memname}String::serialize(Fw::SerializeBufferBase& buffer) const {
NATIVE_UINT_TYPE strSize = strnlen(this->m_buf,sizeof(this->m_buf));
// serialize string
return buffer.serialize((U8*)this->m_buf,strSize);
}
Fw::SerializeStatus ${name}::${memname}String::deserialize(Fw::SerializeBufferBase& buffer) {
NATIVE_UINT_TYPE maxSize = sizeof(this->m_buf);
// deserialize string
Fw::SerializeStatus stat = buffer.deserialize((U8*)this->m_buf,maxSize);
// make sure it is null-terminated
this->terminate(maxSize);
return stat;
}
NATIVE_UINT_TYPE ${name}::${memname}String::getCapacity() const {
return sizeof(this->m_buf);
}
void ${name}::${memname}String::terminate(NATIVE_UINT_TYPE size) {
// null terminate the string
this->m_buf[size < sizeof(this->m_buf)?size:sizeof(this->m_buf)-1] = 0;
}
const ${name}::${memname}String& ${name}::${memname}String::operator=(const ${name}::${memname}String& other) {
this->copyBuff(other.m_buf,this->getCapacity());
return *this;
}
#end if
#end for

View File

@ -19,7 +19,7 @@ namespace ${n} {
class ${name} : public Fw::Serializable {
#for ($memname,$type,$size,$format,$comment) in $mem_list:
#for ($memname,$type,$size,$format,$comment,$default) in $mem_list:
#if $type == "string":
public:
@ -34,22 +34,17 @@ class ${name} : public Fw::Serializable {
${memname}String(const Fw::StringBase& src); //!< string base constructor
${memname}String(const ${memname}String& src); //!< string base constructor
${memname}String(); //!< default constructor
virtual ~${memname}String(); //!< destructor
${memname}String& operator=(const ${memname}String& other); //!< assignment operator
${memname}String& operator=(const Fw::StringBase& other); //!< other string assignment operator
${memname}String& operator=(const char* other); //!< char* assignment operator
~${memname}String(); //!< destructor
const char* toChar() const; //!< retrieves char buffer of string
NATIVE_UINT_TYPE length() const; //!< returns length of string
bool operator==(const ${memname}String& src) const; //!< equality operator
const ${memname}String& operator=(const ${memname}String& other); //!< equal operator for other strings
Fw::SerializeStatus serialize(Fw::SerializeBufferBase& buffer) const; //!< serialization function
Fw::SerializeStatus deserialize(Fw::SerializeBufferBase& buffer); //!< deserialization function
NATIVE_UINT_TYPE getCapacity() const ;
private:
NATIVE_UINT_TYPE getCapacity() const ;
void terminate(NATIVE_UINT_TYPE size); //!< terminate the string
char m_buf[${size}]; //!< buffer for string storage
};
#end if

View File

@ -1,7 +1,15 @@
// public methods
${name}::${name}(): Serializable() {
#for ($member,$type,$size,$format,$comment,$default,$typeinfo) in $members:
#if $default != None and $size != None and $typeinfo != "string":
for (NATIVE_INT_TYPE _mem = 0; _mem < ${size}; _mem++) {
this->m_${member}[_mem] = ${default};
}
#else if $default != None:
this->m_${member} = ${default};
#end if
#end for
}
${name}::${name}(const ${name}& src) : Serializable() {
@ -17,6 +25,21 @@ ${name}::${name}(${args_proto_string}) : Serializable() {
this->set(${args_string});
}
#if $args_scalar_array_string:
${name}::${name}(${args_scalar_array_string}) : Serializable() {
#for ($member,$type,$size,$format,$comment,$default,$typeinfo) in $members:
#if $size == None or $typeinfo == "string":
this->m_${member} = ${member};
#else
for (NATIVE_INT_TYPE _mem = 0; _mem < ${size}; _mem++) {
this->m_${member}[_mem] = ${member};
}
#end if
#end for
}
#end if
const ${name}& ${name}::operator=(const ${name}& src) {
this->set(${args_mstring});
return src;
@ -24,14 +47,14 @@ const ${name}& ${name}::operator=(const ${name}& src) {
bool ${name}::operator==(const ${name}& src) const {
return (
#for ($member,$type,$size,$format,$comment,$typeinfo) in $members:
#for ($member,$type,$size,$format,$comment,$default,$typeinfo) in $members:
(src.m_$member == this->m_$member) &&
#end for
true);
}
void ${name}::set(${args_proto_string}) {
#for ($member,$type,$size,$format,$comment,$typeinfo) in $members:
#for ($member,$type,$size,$format,$comment,$default,$typeinfo) in $members:
#if $size == None or $typeinfo == "string":
this->m_${member} = ${member};
#else
@ -42,7 +65,7 @@ void ${name}::set(${args_proto_string}) {
#end for
}
#for ($member,$type,$size,$format,$comment,$typeinfo) in $members:
#for ($member,$type,$size,$format,$comment,$default,$typeinfo) in $members:
#if $size == None:
${type} ${name}::get${member}() const {
return this->m_${member};
@ -57,7 +80,7 @@ const ${type}* ${name}::get${member}(NATIVE_INT_TYPE& size) const {
}
#end for
#for ($member,$type,$size,$format,$comment,$typeinfo) in $members:
#for ($member,$type,$size,$format,$comment,$default,$typeinfo) in $members:
#if $size == None:
void ${name}::set${member}(${type} val) {
this->m_${member} = val;
@ -82,7 +105,7 @@ Fw::SerializeStatus ${name}::serialize(Fw::SerializeBufferBase& buffer) const {
stat = buffer.serialize((U32)${name}::TYPE_ID);
\#endif
#for ($member,$type,$size,$format,$comment,$typeinfo) in $members:
#for ($member,$type,$size,$format,$comment,$default,$typeinfo) in $members:
#if $size == None or $typeinfo == "string":
#if $typeinfo == "enum":
stat = buffer.serialize((FwEnumStoreType)this->m_${member});
@ -120,7 +143,7 @@ Fw::SerializeStatus ${name}::deserialize(Fw::SerializeBufferBase& buffer) {
}
\#endif
#for ($member,$type,$size,$format,$comment,$typeinfo) in $members:
#for ($member,$type,$size,$format,$comment,$default,$typeinfo) in $members:
#if $size == None or $typeinfo == "string":
#if $typeinfo == "enum"
FwEnumStoreType int${member} = 0;
@ -150,7 +173,7 @@ void ${name}::toString(Fw::StringBase& text) const {
static const char * formatString =
"("
#for ($member,$type,$size,$format,$comment,$typeinfo) in $members[0:-1]:
#for ($member,$type,$size,$format,$comment,$default,$typeinfo) in $members[0:-1]:
#if $size != None and typeinfo != "string":
"$member = "
#for $elem in range(0,int($size)-1):
@ -174,17 +197,17 @@ void ${name}::toString(Fw::StringBase& text) const {
// declare strings to hold any serializable toString() arguments
#for ($member,$type,$size,$format,$comment,$typeinfo) in $members:
#for ($member,$type,$size,$format,$comment,$default,$typeinfo) in $members:
#if $typeinfo == "extern":
Fw::EightyCharString ${member}Str;
Fw::String ${member}Str;
this->m_${member}.toString(${member}Str);
#end if
#end for
char outputString[FW_SERIALIZABLE_TO_STRING_BUFFER_SIZE];
(void)snprintf(outputString,FW_SERIALIZABLE_TO_STRING_BUFFER_SIZE,formatString
#for ($member,$type,$size,$format,$comment,$typeinfo) in $members:
#for ($member,$type,$size,$format,$comment,$default,$typeinfo) in $members:
#if $size != None and $typeinfo != "string":
#for $elem in range(0,int($size)):
#if $type == "bool":
@ -219,7 +242,7 @@ void ${name}::toString(Fw::StringBase& text) const {
\#ifdef BUILD_UT
std::ostream& operator<<(std::ostream& os, const ${name}& obj) {
Fw::EightyCharString str;
Fw::String str;
obj.toString(str);
os << str.toChar();
return os;

View File

@ -29,6 +29,9 @@ public:
${name}(const ${name}* src); //!< pointer copy constructor
${name}(const ${name}& src); //!< reference copy constructor
${name}($args_proto); //!< constructor with arguments
#if $args_proto_scalar_init:
${name}($args_proto_scalar_init); //!< constructor with arguments with scalars for array arguments
#end if
const ${name}& operator=(const ${name}& src); //!< equal operator
bool operator==(const ${name}& src) const; //!< equality operator
#ifdef BUILD_UT

View File

@ -85,7 +85,7 @@ class SerialCppVisitor(AbstractVisitor.AbstractVisitor):
for use in templates that generate prototypes.
"""
arg_str = ""
for (name, mtype, size, format, comment) in obj.get_members():
for (name, mtype, size, format, comment, default) in obj.get_members():
if isinstance(mtype, tuple):
arg_str += "{} {}, ".format(mtype[0][1], name)
elif mtype == "string":
@ -128,7 +128,7 @@ class SerialCppVisitor(AbstractVisitor.AbstractVisitor):
"""
arg_list = list()
for (name, mtype, size, format, comment) in obj.get_members():
for (name, mtype, size, format, comment, default) in obj.get_members():
typeinfo = None
if isinstance(mtype, tuple):
mtype = mtype[0][1]
@ -139,10 +139,36 @@ class SerialCppVisitor(AbstractVisitor.AbstractVisitor):
elif mtype not in typelist:
typeinfo = "extern"
arg_list.append((name, mtype, size, format, comment, typeinfo))
arg_list.append((name, mtype, size, format, comment, default, typeinfo))
return arg_list
def _get_args_proto_string_scalar_init(self, obj):
"""
Return a string of (type, name) args, comma separated
for use in templates that generate prototypes where the array
arguments are represented by single element values. If no arguments
are arrays, function returns None.
"""
arg_str = ""
contains_array = False
for (name, mtype, size, format, comment, default) in obj.get_members():
if isinstance(mtype, tuple):
arg_str += "{} {}, ".format(mtype[0][1], name)
elif mtype == "string":
arg_str += "const {}::{}String& {}, ".format(obj.get_name(), name, name)
elif mtype not in typelist:
arg_str += "const {}& {}, ".format(mtype, name)
elif size is not None:
arg_str += "const {} {}, ".format(mtype, name)
contains_array = True
else:
arg_str += "{} {}".format(mtype, name)
arg_str += ", "
if not contains_array:
return None
arg_str = arg_str.strip(", ")
return arg_str
def _writeTmpl(self, c, visit_str):
"""
Wrapper to write tmpl to files desc.
@ -267,6 +293,7 @@ class SerialCppVisitor(AbstractVisitor.AbstractVisitor):
c.args_string = self._get_args_string(obj)
c.args_mstring = self._get_args_string(obj, "src.m_")
c.args_mstring_ptr = self._get_args_string(obj, "src->m_")
c.args_scalar_array_string = self._get_args_proto_string_scalar_init(obj)
c.members = self._get_conv_mem_list(obj)
self._writeTmpl(c, "publicVisit")

View File

@ -88,7 +88,7 @@ class SerialHVisitor(AbstractVisitor.AbstractVisitor):
for use in templates that generate prototypes.
"""
arg_str = ""
for (name, mtype, size, format, comment) in obj.get_members():
for (name, mtype, size, format, comment, default) in obj.get_members():
if isinstance(mtype, tuple):
arg_str += "{} {}, ".format(mtype[0][1], name)
elif mtype == "string":
@ -105,13 +105,40 @@ class SerialHVisitor(AbstractVisitor.AbstractVisitor):
arg_str = arg_str.strip(", ")
return arg_str
def _get_args_string_scalar_init(self, obj):
"""
Return a string of (type, name) args, comma separated
where array arguments are represented by single element
values for use in templates that generate prototypes.
If no arguments are arrays, function returns None.
"""
arg_str = ""
contains_array = False
for (name, mtype, size, format, comment, default) in obj.get_members():
if isinstance(mtype, tuple):
arg_str += "{} {}, ".format(mtype[0][1], name)
elif mtype == "string":
arg_str += "const {}::{}String& {}, ".format(obj.get_name(), name, name)
elif mtype not in typelist:
arg_str += "const {}& {}, ".format(mtype, name)
elif size is not None:
arg_str += "const {} {}, ".format(mtype, name)
contains_array = True
else:
arg_str += "{} {}".format(mtype, name)
arg_str += ", "
if not contains_array:
return None
arg_str = arg_str.strip(", ")
return arg_str
def _get_conv_mem_list(self, obj):
"""
Return a list of port argument tuples
"""
arg_list = list()
for (name, mtype, size, format, comment) in obj.get_members():
for (name, mtype, size, format, comment, default) in obj.get_members():
typeinfo = None
if isinstance(mtype, tuple):
mtype = mtype[0][1]
@ -282,6 +309,7 @@ class SerialHVisitor(AbstractVisitor.AbstractVisitor):
c = publicSerialH.publicSerialH()
c.name = obj.get_name()
c.args_proto = self._get_args_string(obj)
c.args_proto_scalar_init = self._get_args_string_scalar_init(obj)
c.members = self._get_conv_mem_list(obj)
self._writeTmpl(c, "publicVisit")

View File

@ -56,6 +56,7 @@ class XmlEnumParser:
self.__name = ""
self.__namespace = None
self.__default = None
self.__serialize_type = None
self.__xml_filename = xml_file
self.__items = []
@ -107,6 +108,11 @@ class XmlEnumParser:
else:
self.__default = None
if "serialize_type" in enum.attrib:
self.__serialize_type = enum.attrib["serialize_type"]
else:
self.__serialize_type = None
for enum_tag in enum:
if enum_tag.tag == "item":
item = enum_tag.attrib
@ -207,6 +213,9 @@ class XmlEnumParser:
def get_default(self):
return self.__default
def get_serialize_type(self):
return self.__serialize_type
def get_items(self):
return self.__items
@ -221,8 +230,13 @@ if __name__ == "__main__":
print("Enum XML parse test (%s)" % xmlfile)
xml_parser = XmlEnumParser(xmlfile)
print(
"Enum name: %s, namespace: %s, default: %s"
% (xml_parser.get_name(), xml_parser.get_namespace(), xml_parser.get_default())
"Enum name: %s, namespace: %s, default: %s, serialize_type: %s"
% (
xml_parser.get_name(),
xml_parser.get_namespace(),
xml_parser.get_default(),
xml_parser.get_serialize_type(),
)
)
print("Items")
for item in xml_parser.get_items():

View File

@ -206,6 +206,8 @@ class XmlSerializeParser:
else:
c = None
d = None
for member_tag in member:
if member_tag.tag == "enum" and t == "ENUM":
en = member_tag.attrib["name"]
@ -222,6 +224,8 @@ class XmlSerializeParser:
mc = None
enum_members.append((mn, v, mc))
t = ((t, en), enum_members)
elif member_tag.tag == "default":
d = member_tag.text
else:
PRINT.info(
"%s: Invalid member tag %s in serializable member %s"
@ -229,7 +233,7 @@ class XmlSerializeParser:
)
sys.exit(-1)
self.__members.append((n, t, s, f, c))
self.__members.append((n, t, s, f, c, d))
#
# Generate a type id here using SHA256 algorithm and XML stringified file.

View File

@ -37,13 +37,16 @@ def open_file(name, type):
return fp
def write_template(fp, c, name, namespace, default, items, max_value, comment):
def write_template(
fp, c, name, namespace, default, serialize_type, items, max_value, comment
):
"""
Set up and write out templates here
"""
c.name = name
c.namespace = namespace
c.default = default
c.serialize_type = serialize_type
c.items_list = items
c.max_value = max_value
c.comment = comment
@ -65,6 +68,7 @@ def generate_enum(xml_file):
name = enum_xml.get_name()
namespace = enum_xml.get_namespace()
default = enum_xml.get_default()
serialize_type = enum_xml.get_serialize_type()
items = enum_xml.get_items()
max_value = enum_xml.get_max_value()
comment = enum_xml.get_comment()
@ -73,14 +77,18 @@ def generate_enum(xml_file):
#
fp = open_file(name, "hpp")
c = enum_hpp.enum_hpp()
write_template(fp, c, name, namespace, default, items, max_value, comment)
write_template(
fp, c, name, namespace, default, serialize_type, items, max_value, comment
)
fp.close()
#
# Generate the cpp file
#
fp = open_file(name, "cpp")
c = enum_cpp.enum_cpp()
write_template(fp, c, name, namespace, default, items, max_value, comment)
write_template(
fp, c, name, namespace, default, serialize_type, items, max_value, comment
)
fp.close()
return True
else:

View File

@ -72,12 +72,15 @@ class TopDictGenerator:
member_size,
member_format_specifier,
member_comment,
member_default,
) in serializable_model.get_members():
member_elem = etree.Element("member")
member_elem.attrib["name"] = member_name
member_elem.attrib["format_specifier"] = member_format_specifier
if member_comment is not None:
member_elem.attrib["description"] = member_comment
if member_default is not None:
member_elem.attrib["default"] = member_default
if isinstance(member_type, tuple):
type_name = "{}::{}::{}".format(
serializable_type,

View File

@ -1,8 +1,6 @@
#include <Autocoders/Python/templates/ExampleType.hpp>
#include <Fw/Types/Assert.hpp>
#if FW_SERIALIZABLE_TO_STRING
#include <Fw/Types/EightyCharString.hpp>
#endif
namespace ANameSpace {
mytype::mytype(): Serializable() {

View File

@ -1,57 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Note: sync attribute can be sync, async, or guarded. Only for input />
Note: priority attribute can be high, medium, low or interrupt.
Only valid for active components input.
Note kind attribute of component can be ether active or passive.
-->
<component name="ActiveRateGroup" kind="active" namespace="Svc">
<import_port_type>Svc/Sched/SchedPortAi.xml</import_port_type>
<import_port_type>Svc/Cycle/CyclePortAi.xml</import_port_type>
<comment>A rate group active component with input and output scheduler ports</comment>
<ports>
<!-- Input time cycle port -->
<port name="CycleIn" data_type="Cycle" kind="async_input" max_number="1">
<comment>
The rate group cycle input
</comment>
</port>
<!-- Output Scheduler Ports -->
<port name="RateGroupMemberOut" data_type="Sched" kind="output" max_number="$ActiveRateGroupOutputPorts">
<comment>Scheduler output port to rate group members</comment>
</port>
</ports>
<telemetry telemetry_base="$ActiveRateGroupTelemetryBase">
<channel id="0" name="RgMaxTime" data_type="U32" abbrev="S001-0000" update="on_change" format_string = "%u us">
<comment>
Max execution time rate group
</comment>
</channel>
<channel id="1" name="RgCycleSlips" data_type="U32" abbrev="S001-0001" update="on_change">
<comment>
Cycle slips for rate group
</comment>
</channel>
</telemetry>
<events event_base="$ActiveRateGroupEventsBase">
<event id="0" name="RateGroupStarted" severity="DIAGNOSTIC" format_string = "Rate group started." >
<comment>
Informational event that rate group has started
</comment>
</event>
<event id="1" name="RateGroupCycleSlip" severity="WARNING_HI" format_string = "Rate group cycle slipped on cycle %d" >
<comment>
Warning event that rate group has had a cycle slip
</comment>
<args>
<arg name="cycle" type="U32">
<comment>The cycle where the cycle occurred</comment>
</arg>
</args>
</event>
</events>
</component>

View File

@ -10,6 +10,7 @@ add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/command1")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/command2")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/comp_diff_namespace")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/comp_no_namespace")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/crisscross")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/enum_return_port")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/enum_xml")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/enum1port")
@ -39,17 +40,16 @@ add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/queued1")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/serial_passive")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/serialize_enum")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/serialize_stringbuffer")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/time_get")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/crisscross")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/serialize_user")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/serialize1")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/serialize2")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/serialize3")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/serialize4")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/stress")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/string_port")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/telem_tester")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/testgen")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/time_get")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/time_tester")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/tlm_enum")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/tlm_multi_inst")

View File

@ -22,43 +22,21 @@
using namespace std;
// Registry
static Fw::SimpleObjRegistry* simpleReg_ptr = 0;
// Component instance pointers
Example::ExampleArrayImpl* inst1 = 0;
Example::ExampleArrayImpl* inst2 = 0;
extern "C" {
void dumparch();
void dumpobj(const char* objName);
}
#ifdef TGT_OS_TYPE_LINUX
extern "C" {
int main(int argc, char* argv[]);
};
#endif
void dumparch() {
simpleReg_ptr->dump();
}
void dumpobj(const char* objName) {
simpleReg_ptr->dump(objName);
}
void constructArchitecture() {
Fw::PortBase::setTrace(true);
simpleReg_ptr = new Fw::SimpleObjRegistry();
dumparch();
}
int main(int argc, char* argv[]) {
// Construct the topology here.
constructArchitecture();
Fw::PortBase::setTrace(true);
Fw::SimpleObjRegistry simpleReg_ptr;
simpleReg_ptr.dump();
setbuf(stdout, NULL);
@ -156,7 +134,6 @@ int main(int argc, char* argv[]) {
delete inst1;
delete inst2;
cout << "Delete registration objects..." << endl;
delete simpleReg_ptr;
cout << "Completed..." << endl;
return 0;

View File

@ -1,21 +0,0 @@
#!/bin/sh -e
export GREEN='\033[32m'
export RED='\033[31m'
export NO_COLOR='\033[0m'
files=`find . -name CMakeLists.txt | xargs grep -l '^register_fprime_ut' | sort | uniq`
here=$PWD
for file in $files
do
dir=`dirname $file`
printf '%-60s' $dir
cd $dir
if fprime-util build --ut > /dev/null 2>&1
then
echo $GREEN'OK'$NO_COLOR
else
echo $RED'FAILED'$NO_COLOR
fi
cd $here
done

View File

@ -1,21 +0,0 @@
#!/bin/sh -e
export GREEN='\033[32m'
export RED='\033[31m'
export NO_COLOR='\033[0m'
files=`find . -name CMakeLists.txt | xargs grep -l '^register_fprime_ut' | sort | uniq`
here=$PWD
for file in $files
do
dir=`dirname $file`
printf '%-60s' $dir
cd $dir
if fprime-util check 2>&1 | grep -q '100% tests passed'
then
echo $GREEN'PASSED'$NO_COLOR
else
echo $RED'FAILED'$NO_COLOR
fi
cd $here
done

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<enum namespace="EnumTyp" name="ExampleEnum"
<item name="HSM_NOT_USED" value="0" comment="Not used"/>
<item name="HSM_NOMINAL" value="1" comment="Nominal ops"/>
<item name="HSM_IDLE" value="2" comment="Idel state"/>
<item name="HSM_SOFT_SAFE" value="3" comment="Soft safe mode"/>
<item name="HSM_OFF" value="4" comment="Off"/>
<item name="HSM_MAX" value="5" comment="Maximum value limit"/>
</enum>

View File

@ -8,6 +8,7 @@ set(SOURCE_FILES
"${CMAKE_CURRENT_LIST_DIR}/Component1ComponentAi.xml"
"${CMAKE_CURRENT_LIST_DIR}/Enum1EnumAi.xml"
"${CMAKE_CURRENT_LIST_DIR}/Enum2EnumAi.xml"
"${CMAKE_CURRENT_LIST_DIR}/Enum3EnumAi.xml"
"${CMAKE_CURRENT_LIST_DIR}/Port1PortAi.xml"
"${CMAKE_CURRENT_LIST_DIR}/Serial1SerializableAi.xml"
)

View File

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<component name="Component1" kind="active" namespace="Example">
<import_enum_type>Autocoders/Python/test/enum_xml/Enum2EnumAi.xml</import_enum_type>
<import_enum_type>Autocoders/Python/test/enum_xml/Enum3EnumAi.xml</import_enum_type>
<import_port_type>Autocoders/Python/test/enum_xml/Port1PortAi.xml</import_port_type>
<import_serializable_type>Autocoders/Python/test/enum_xml/Serial1SerializableAi.xml</import_serializable_type>
<import_dictionary>Autocoders/Python/test/enum_xml/Telemetry.xml</import_dictionary>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<enum namespace = "Example" name="Enum2">
<enum namespace = "Example" name="Enum2" serialize_type="U64">
<comment>Test enum_xml example enum</comment>
<item name="Item1" value="-1952875139"/>
<item name="Item2" value="2"/>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<enum namespace = "Example" name="Enum3" serialize_type="U8">
<comment>Test enum_xml example enum</comment>
<item name="Item1" value="-1952875139"/>
<item name="Item2" value="2"/>
<item name="Item3" comment="Test Item" value="2000999333"/>
<item name="Item4" value="21"/>
<item name="Item5" value="-8324876"/>
</enum>

View File

@ -7,8 +7,7 @@
<members>
<member name="Member1" type="U32" comment = "Example member 1"/>
<member name="Member2" type="U32" comment = "Example member 2"/>
<member name="Member3" type="Example::Enum1" comment = "Example enum member">
</member>
<member name="Member3" type="Example::Enum1" comment = "Example enum member"/>
</members>
</serializable>

View File

@ -179,6 +179,7 @@ TEST(EnumXML, OK) {
Example::Enum1 enum2;
Example::Enum1 enum3;
Example::Enum2 enum4;
Example::Enum3 enum5;
Example::Serial1 serial1;
@ -189,6 +190,11 @@ TEST(EnumXML, OK) {
// Check that enum are set to uninitialized value
ASSERT_EQ(enum4.e, 0);
// Check that the enum serializable types are set correctly
ASSERT_EQ(Example::Enum1::SERIALIZED_SIZE, sizeof(FwEnumStoreType));
ASSERT_EQ(Example::Enum2::SERIALIZED_SIZE, sizeof(U64));
ASSERT_EQ(Example::Enum3::SERIALIZED_SIZE, sizeof(U8));
enum1 = getEnumFromI32();
cout << "Created first enum: " << enum1 << endl;
@ -209,16 +215,38 @@ TEST(EnumXML, OK) {
// Serialize enums
U8 buffer1[1024];
U8 buffer2[1024];
U8 buffer3[1024];
U8 buffer4[1024];
U8 buffer5[1024];
Fw::SerialBuffer enumSerial1 = Fw::SerialBuffer(buffer1, sizeof(buffer1));
Fw::SerialBuffer enumSerial2 = Fw::SerialBuffer(buffer2, sizeof(buffer2));
Fw::SerialBuffer enumSerial3 = Fw::SerialBuffer(buffer3, sizeof(buffer3));
Fw::SerialBuffer enumSerial4 = Fw::SerialBuffer(buffer4, sizeof(buffer4));
Fw::SerialBuffer enumSerial5 = Fw::SerialBuffer(buffer5, sizeof(buffer5));
ASSERT_EQ(enumSerial1.serialize(enum1), Fw::FW_SERIALIZE_OK);
cout << "Serialized enum1" << endl;
ASSERT_EQ(enumSerial2.serialize(enum2), Fw::FW_SERIALIZE_OK);
cout << "Serialized enum2" << endl;
ASSERT_EQ(enumSerial3.serialize(enum3), Fw::FW_SERIALIZE_OK);
cout << "Serialized enum3" << endl;
ASSERT_EQ(enumSerial4.serialize(enum4), Fw::FW_SERIALIZE_OK);
cout << "Serialized enum4" << endl;
ASSERT_EQ(enumSerial5.serialize(enum5), Fw::FW_SERIALIZE_OK);
cout << "Serialized enum5" << endl;
cout << "Serialized enums" << endl;
// Check that the serialized types are correctly set
ASSERT_EQ(enumSerial1.getBuffLength(), sizeof(FwEnumStoreType));
ASSERT_EQ(enumSerial2.getBuffLength(), sizeof(FwEnumStoreType));
ASSERT_EQ(enumSerial3.getBuffLength(), sizeof(FwEnumStoreType));
ASSERT_EQ(enumSerial4.getBuffLength(), sizeof(U64));
ASSERT_EQ(enumSerial5.getBuffLength(), sizeof(U8));
// Deserialize enums
ASSERT_EQ(enumSerial1.deserialize(enum1Save), Fw::FW_SERIALIZE_OK);
cout << "Deserialized enum1" << endl;

View File

@ -44,8 +44,9 @@ Fw::SerializeStatus UserSerializer::serialize(Fw::SerializeBufferBase& buffer) c
Fw::SerializeStatus UserSerializer::deserialize(Fw::SerializeBufferBase& buffer) {
NATIVE_UINT_TYPE serSize = sizeof(m_struct);
return buffer.deserialize((U8*)&m_struct,serSize);
Fw::SerializeStatus stat = buffer.deserialize((U8*)&m_struct,serSize);
FW_ASSERT(serSize == sizeof(m_struct));
return stat;
}

View File

@ -1,13 +0,0 @@
[nosetests]
where=.
;Declaring multiple directories not allowed in ini file
;Throws error: ValueError: Working directory '. app1 app2' not found, or not a directory
;
;where=app1
;where=. app1 app2

View File

@ -1,39 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<component name="C1" kind="active" namespace="Passive">
<import_port_type>VoidInterfaceAi.xml</import_port_type>
<import_port_type>Msg1InterfaceAi.xml</import_port_type>
<import_port_type>Msg2InterfaceAi.xml</import_port_type>
<comment>
A demonstration component that contains three input
ports and two output ports for driving a passive
component.
six instances
</comment>
<ports>
<!-- First port defined is external void for main code calling -->
<port name="Ext1" data_type="Void" kind="async_input">
<comment>The input port has no args and is external interface</comment>
</port>
<!-- Second port defined is external Msg1 type with args -->
<port name="Ext2" data_type="Msg1" kind="async_input">
<comment>The input port of type Msg1 has args</comment>
</port>
<!-- Third port defined is sync input of Msg2 type with args -->
<port name="Sync" data_type="Msg2" kind="sync_input">
<comment>The output port of type Void has no args</comment>
</port>
<!-- Forth port defined is output with no args of type Void -->
<port name="Void" data_type="Void" kind="output">
<comment>The output port of type Void has no args and drives a sync input</comment>
</port>
<!-- Fith port defined is output with three args of type Msg1 -->
<port name="Msg1" data_type="Msg1" kind="output">
<comment>The output port of type Msg1 has three args and drives a sync input</comment>
</port>
</ports>
</component>

View File

@ -1,24 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<component name="C2" kind="passive" namespace="Passive">
<import_port_type>VoidInterfaceAi.xml</import_port_type>
<import_port_type>Msg1InterfaceAi.xml</import_port_type>
<import_port_type>Msg2InterfaceAi.xml</import_port_type>
<comment>
A demonstration passive component with two input ports and one output port.
All ports are synchronous typed.
</comment>
<ports>
<port name="Void" data_type="Void" kind="sync_input">
<comment/>
</port>
<port name="Msg1" data_type="Msg1" kind="sync_input">
<comment/>
</port>
<port name="Msg2" kind="output" data_type="Msg2">
<comment/>
</port>
</ports>
</component>

View File

@ -1,19 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface name="Msg1" namespace="Ports">
<include_header>Fw/Types/FwStringType</include_header>
<comment>
Msg Interface to send arg1, arg2 and arg3 arguments.
</comment>
<args>
<arg name="arg1" type="U32">
<comment>The U32 arg1 argument</comment>
</arg>
<arg name="arg2" type="I32">
<comment>The I32 arg2 argument</comment>
</arg>
<arg name="arg3" type="F32">
<comment>The F32 arg3 argument</comment>
</arg>
</args>
</interface>

View File

@ -1,23 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface name="Msg2" namespace="Ports">
<include_header>Fw/Types/FwStringType</include_header>
<include_header>Fw/Types/FwEightyCharString</include_header>
<comment>
Msg Interface to send arg1, arg2 and arg3 arguments.
</comment>
<args>
<arg name="arg1" type="U32">
<comment>The U32 arg1 argument</comment>
</arg>
<arg name="arg2" type="I32">
<comment>The I32 arg2 argument</comment>
</arg>
<arg name="arg3" type="F32">
<comment>The F32 arg3 argument</comment>
</arg>
<arg name="str" type="Fw::EightyCharString">
<comment>The 80 character string str argument</comment>
</arg>
</args>
</interface>

View File

@ -1,41 +0,0 @@
#include <Autocoders/Python/test/passive/PassiveC1Impl.hpp>
#include <Fw/Types/FwBasicTypes.hpp>
#include <iostream>
#include <stdio.h>
using namespace std;
namespace Passive {
C1Impl::C1Impl(const char* compName) : C1Base(compName) {
}
C1Impl::~C1Impl() {
}
// Internal call - implemented by hand.
// downcall for input port Ext1
I32 C1Impl::Ext1_Void_handler() {
printf("*** %s: Ext1_Void_handler down-call\n", this->m_objName);
this->Void_Void_out();
return 0;
}
// downcall for input port Ext2
I32 C1Impl::Ext2_Msg1_handler(U32 arg1, I32 arg2, F32 arg3) {
printf("*** %s: Ext2_Msg1_handler(%u,%ld,%f) down-call\n", this->m_objName, arg1, arg2, arg3);
this->Msg1_Msg1_out(arg1,arg2,arg3);
return 0;
}
// downcall for input port Sync
I32 C1Impl::Sync_Msg2_handler(U32 arg1, I32 arg2, F32 arg3, Fw::EightyCharString str) {
printf("*** %s: Sync_Msg2_handler(%u,%ld,%f,%s) down-call\n", this->m_objName, arg1,arg2,arg3,(char *)str.toChar());
return 0;
}
};

View File

@ -1,26 +0,0 @@
#ifndef PASSIVEC1IMPL_HPP
#define PASSIVEC1IMPL_HPP
#include <Autocoders/Python/test/passive/PassiveC1ComponentAc.hpp>
namespace Passive {
class C1Impl : public C1Base {
public:
// Only called by derived class
C1Impl(const char* compName);
~C1Impl();
private:
// downcall for input ports
I32 Ext1_Void_handler();
I32 Ext2_Msg1_handler(U32 arg1, I32 arg2, F32 arg3);
I32 Sync_Msg2_handler(U32 arg1, I32 arg2, F32 arg3, Fw::EightyCharString str);
};
};
#endif

View File

@ -1,34 +0,0 @@
#include <Autocoders/Python/test/passive/PassiveC2Impl.hpp>
#include <Fw/Types/FwBasicTypes.hpp>
#include <iostream>
#include <stdio.h>
using namespace std;
namespace Passive {
C2Impl::C2Impl(const char* compName) : C2Base(compName) {
}
C2Impl::~C2Impl() {
}
// Internal call - implemented by hand.
// downcall for input port Void
I32 C2Impl::Void_Void_handler() {
printf("*** %s: Void_Void_handler down-call\n", this->m_objName);
return 0;
}
// downcall for input port Msg1
I32 C2Impl::Msg1_Msg1_handler(U32 arg1, I32 arg2, F32 arg3) {
printf("*** %s: Msg1_Msg1_handler(%u,%ld,%f) down-call\n", this->m_objName,arg1,arg2,arg3);
this->Msg2_Msg2_out(arg1,arg2,arg3,"Synchronous Test String");
return 0;
}
};

View File

@ -1,25 +0,0 @@
#ifndef PASSIVEC2IMPL_HPP
#define PASSIVEC2IMPL_HPP
#include <Autocoders/Python/test/passive/PassiveC2ComponentAc.hpp>
namespace Passive {
class C2Impl : public C2Base {
public:
// Only called by derived class
C2Impl(const char* compName);
~C2Impl();
private:
// downcall for input ports
I32 Void_Void_handler();
I32 Msg1_Msg1_handler(U32 arg1, I32 arg2, F32 arg3);
};
};
#endif

View File

@ -1,15 +0,0 @@
Date: 10 May. 2013
This test case builds a passive component called Passive with a single input
and output port to demonstrate the code generation of a passive component
with only typed ports.
In the future this will be automated.
1. Execute ../../bin/yacgen.py PassiveComponentAi.xml
2. Execute ../../bin/yacgen.py TypedInterfaceAi.xml
3. Execute scons
4. Execute ./Top
It should work.

View File

@ -1,109 +0,0 @@
#include <Autocoders/Python/test/app1b/Top.hpp>
#include <Fw/Obj/SimpleObjRegistry.hpp>
#include <iostream>
#include <string.h>
#include <Autocoders/Python/test/passive/PassiveC1Impl.hpp>
#include <Autocoders/Python/test/passive/PassiveC2Impl.hpp>
#include <unistd.h>
using namespace std;
// Registry
static Fw::SimpleObjRegistry* simpleRegPtr = 0;
// Component instance pointers
Passive::C1Impl* C1_ptr = 0;
Passive::C2Impl* C2_ptr = 0;
extern "C" {
void dumparch();
void dumpobj(const char* objName);
}
void dumparch() {
simpleRegPtr->dump();
}
void dumpobj(const char* objName) {
simpleRegPtr->dump(objName);
}
void constructArchitecture() {
Fw::PortBase::setTrace(true);
simpleRegPtr = new Fw::SimpleObjRegistry();
// Instantiate the C1 and C2 components
C1_ptr = new Passive::C1Impl("C1");
C2_ptr = new Passive::C2Impl("C2");
// Connect C1 output ports to C2 input ports.
C1_ptr->getVoidVoidOutputPort()->addCallPort(C2_ptr->getVoidVoidInputPort());
C1_ptr->getMsg1Msg1OutputPort()->addCallPort(C2_ptr->getMsg1Msg1InputPort());
// Connect C2 output ports to C1 input ports.
C2_ptr->getMsg2Msg2OutputPort()->addCallPort(C1_ptr->getSyncMsg2InputPort());
// Active component startup
// start(identifier, stack size, priority)
C1_ptr->start(0, 10 * 1024, 100);
dumparch();
}
#ifdef TGT_OS_TYPE_LINUX
extern "C" {
int main(int argc, char* argv[]);
};
#endif
int main(int argc, char* argv[]) {
// Construct the topology here.
constructArchitecture();
// Ask for input to huey or duey here.
char in[80];
int in2;
U32 a1;
I32 a2;
F32 a3;
//
while ( strcmp(in,"quit") != 0) {
//
cout << "\nEnter interface number (1 or 2 or quit): ";
cin >> in;
//
if (in[0]=='1') {
C1_ptr->getExt1VoidInputPort()->msg_in();
} else if (in[0] == '2') {
cout << "\nEnter (U32 arg1, I32 arg2, F32 arg3): \n";
cin >> a1;
cin >> a2;
cin >> a3;
cout << "C2_ptr->getExt2Msg1InputPort()->msg_in(" << a1 << "," << a2 << "," << a3 << ")" << endl;
C1_ptr->getExt2Msg1InputPort()->msg_in(a1,a2,a3);
} else if (strcmp(in,"quit")==0) {
cout << "quit demo!" << endl;
} else {
cout << "Unrecognized component." << endl;
};
// Delay to allow components to print messages
sleep(2);
}
cout << "Deleting components..." << endl;
delete C1_ptr;
delete C2_ptr;
cout << "Delete registration objects..." << endl;
delete simpleRegPtr;
cout << "Completed..." << endl;
return 0;
}

View File

@ -1,8 +0,0 @@
#ifndef TOP_TARGET_INIT_HPP
#define TOP_TARGET_INIT_HPP
extern "C" {
void localTargetInit();
}
#endif

View File

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface name="Void" namespace="Ports">
<comment>
Void Interface to send an async call without any arguments.
</comment>
</interface>

View File

@ -1,10 +0,0 @@
; Override default include paths here for testing.
[component]
XMLDefaultFileName = True
[port]
XMLDefaultFileName = True
[includes]
comp_include_path=Autocoders/Python/test/passive
port_include_path=Autocoders/Python/test/passive

View File

@ -1 +0,0 @@
`nosetests --where=. app1 app2 cnt_only active_tester command1_b -v`

View File

@ -0,0 +1,22 @@
# ======================================================================
# CMakeLists.txt
# ======================================================================
# We need to declare the XML source files this way to invoke the autocoder.
# However, only the UT build is allowed here.
set(SOURCE_FILES
"${CMAKE_CURRENT_LIST_DIR}/Serial1SerializableAi.xml"
)
register_fprime_module()
# Declare dependencies on test modules
set(UT_MOD_DEPS
Fw/Test
STest
)
# List all .cpp files as UT_SOURCE_FILES. Only the UT build is allowed.
set(UT_SOURCE_FILES
"${CMAKE_CURRENT_LIST_DIR}/main.cpp"
)
register_fprime_ut()

View File

@ -0,0 +1,10 @@
# Autocoders/Python/test/serialize4
This directory contains unit tests for the Python serialize XML code generator.
To use this directory, you must have installed F Prime, and you must be inside
the F Prime Python virtual environment.
* To build the tests, run `./build`
* To run the tests, run `./run`
* To run coverage analysis, run `./cov`

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<serializable namespace="Example" name="Serial1">
<comment>
Some Example Members
</comment>
<members>
<member name="Member1" type="U32" comment = "Example member 1">
<default>12345</default>
</member>
<member name="Member2" type="string" size="16" comment = "Example member 2">
<default>"hello"</default>
</member>
<member name="Member3" type="ENUM" comment = "Example member 3">
<enum name="SomeEnum">
<item name="MEM1"/>
<item name="MEM2" value="7" />
<item name="MEM3" value="15"/>
</enum>
<default>MEM2</default>
</member>
<member name="Member4" type="U32" size="3" comment = "Example member 4">
<default>3</default>
</member>
</members>
</serializable>

View File

@ -0,0 +1,3 @@
#!/bin/sh
fprime-util build --ut $@

View File

@ -0,0 +1,3 @@
#!/bin/sh
fprime-util coverage $@

View File

@ -0,0 +1,45 @@
#include <Autocoders/Python/test/serialize4/Serial1SerializableAc.hpp>
#include "gtest/gtest.h"
using namespace std;
TEST(DefaultValues, OK) {
Example::Serial1 serial1;
Example::Serial1 serial2;
// Check serializable default values are correctly set
ASSERT_EQ(serial1.getMember1(), 12345);
ASSERT_EQ(serial1.getMember2(), "hello");
ASSERT_EQ(serial1.getMember3(), Example::MEM2);
// Check serializable scalar default for array member is correctly set
NATIVE_INT_TYPE size;
const U32* serial1Member4 = serial1.getMember4(size);
for (NATIVE_INT_TYPE _mem = 0; _mem < size; _mem++) {
ASSERT_EQ(serial1Member4[_mem], 3);
}
}
TEST(Serialize4, ArrayScalarInit) {
Example::Serial1 serial1 (0,"hello world",Example::SomeEnum::MEM2,2);
// Check serializable array member values are correctly set
NATIVE_INT_TYPE size;
const U32* serialMember4 = serial1.getMember4(size);
for (NATIVE_INT_TYPE _mem = 0; _mem < size; _mem++) {
ASSERT_EQ(serialMember4[_mem], 2);
}
}
int main(int argc, char* argv[]) {
::testing::InitGoogleTest(&argc, argv);
int status = RUN_ALL_TESTS();
cout << "Completed..." << endl;
return status;
}

View File

@ -0,0 +1,3 @@
#!/bin/sh
fprime-util check

View File

@ -44,8 +44,9 @@ Fw::SerializeStatus UserSerializer::serialize(Fw::SerializeBufferBase& buffer) c
Fw::SerializeStatus UserSerializer::deserialize(Fw::SerializeBufferBase& buffer) {
NATIVE_UINT_TYPE serSize = sizeof(m_struct);
return buffer.deserialize((U8*)&m_struct,serSize);
Fw::SerializeStatus stat = buffer.deserialize((U8*)&m_struct,serSize);
FW_ASSERT(serSize == sizeof(m_struct));
return stat;
}

View File

@ -18,6 +18,11 @@ set(FPRIME_PROJECT_ROOT "${CMAKE_CURRENT_LIST_DIR}" CACHE PATH "Root path of F p
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Werror -Wno-unused-parameter")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror -Wno-unused-parameter")
# For this testing cmake project, enable AddressSanitizer, a runtime memory sanitizer, on all unit tests
set (CMAKE_C_FLAGS_TESTING "${CMAKE_C_FLAGS_TESTING} -fno-omit-frame-pointer -fsanitize=address")
set (CMAKE_CXX_FLAGS_TESTING "${CMAKE_CXX_FLAGS_TESTING} -fno-omit-frame-pointer -fsanitize=address")
set (CMAKE_LINKER_FLAGS_TESTING "${CMAKE_LINKER_FLAGS_TESTING} -fno-omit-frame-pointer -fsanitize=address")
# Include the build for F prime.
include("${CMAKE_CURRENT_LIST_DIR}/cmake/FPrime.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/cmake/FPrime-Code.cmake")

View File

@ -0,0 +1,17 @@
// ======================================================================
// BlockDriver.hpp
// Standardization header for BlockDriver
// ======================================================================
#ifndef Drv_BlockDriver_HPP
#define Drv_BlockDriver_HPP
#include "Drv/BlockDriver/BlockDriverImpl.hpp"
namespace Drv {
using BlockDriver = BlockDriverImpl;
}
#endif

View File

@ -10,8 +10,8 @@ namespace Drv {
}
void BlockDriverImpl::init(NATIVE_INT_TYPE queueDepth) {
BlockDriverComponentBase::init(queueDepth);
void BlockDriverImpl::init(NATIVE_INT_TYPE queueDepth, NATIVE_INT_TYPE instanceId) {
BlockDriverComponentBase::init(queueDepth, instanceId);
}
BlockDriverImpl::~BlockDriverImpl() {

View File

@ -12,7 +12,7 @@ namespace Drv {
// Only called by derived class
BlockDriverImpl(const char* compName);
void init(NATIVE_INT_TYPE queueDepth);
void init(NATIVE_INT_TYPE queueDepth, NATIVE_INT_TYPE instanceId = 0);
~BlockDriverImpl();
// a little hack to get the reference running
void callIsr();

View File

@ -32,8 +32,12 @@ module Drv {
ref pollBuffer: Fw.Buffer
) -> PollStatus
port ByteStreamReady()
passive component ByteStreamDriverModel {
output port ready: Drv.ByteStreamReady
output port $recv: Drv.ByteStreamRecv
guarded input port send: Drv.ByteStreamSend

View File

@ -14,8 +14,14 @@ add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/LinuxGpioDriver/")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/LinuxSerialDriver/")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/LinuxSpiDriver/")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/LinuxI2cDriver/")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Ip/")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/TcpClient/")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/TcpServer/")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Udp/")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/SocketIpDriver/")
# IP Socket is only supported for Linux, Darwin, VxWorks
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux" OR ${CMAKE_SYSTEM_NAME} STREQUAL "Darwin" OR ${CMAKE_SYSTEM_NAME} STREQUAL "VxWorks")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Ip/")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/TcpClient/")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/TcpServer/")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Udp/")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/SocketIpDriver/")
else()
message(STATUS "Cannot use IP sockets with platform ${CMAKE_SYSTEM_NAME}. Skipping.")
endif()

View File

@ -72,8 +72,8 @@ SocketIpStatus IpSocket::setupTimeouts(NATIVE_INT_TYPE socketFd) {
if (setsockopt(socketFd, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof(timeout)) < 0) {
return SOCK_FAILED_TO_SET_SOCKET_OPTIONS;
}
return SOCK_SUCCESS;
#endif
return SOCK_SUCCESS;
}
SocketIpStatus IpSocket::addressToIp4(const char* address, void* ip4) {
@ -81,11 +81,13 @@ SocketIpStatus IpSocket::addressToIp4(const char* address, void* ip4) {
FW_ASSERT(ip4 != NULL);
// Get the IP address from host
#ifdef TGT_OS_TYPE_VXWORKS
U32 ip = inet_addr(address);
NATIVE_INT_TYPE ip = inet_addr(address);
if (ip == ERROR) {
return SOCK_INVALID_IP_ADDRESS;
}
*ip4 = ip;
// from sin_addr, which has one struct
// member s_addr, which is unsigned int
*reinterpret_cast<unsigned long*>(ip4) = ip;
#else
// First IP address to socket sin_addr
if (not ::inet_pton(AF_INET, address, ip4)) {

View File

@ -45,6 +45,7 @@ enum SocketIpStatus {
class IpSocket {
public:
IpSocket();
virtual ~IpSocket(){};
/**
* \brief configure the ip socket with host and transmission timeouts
*

View File

@ -37,7 +37,12 @@ void SocketReadTask::startSocketTask(const Fw::StringBase &name,
}
SocketIpStatus SocketReadTask::open() {
return this->getSocketHandler().open();
SocketIpStatus status = this->getSocketHandler().open();
// Call connected any time the open is successful
if (Drv::SOCK_SUCCESS == status) {
this->connected();
}
return status;
}
void SocketReadTask::close() {
@ -60,7 +65,7 @@ void SocketReadTask::readTask(void* pointer) {
do {
// Open a network connection if it has not already been open
if ((not self->getSocketHandler().isOpened()) and (not self->m_stop) and
((status = self->getSocketHandler().open()) != SOCK_SUCCESS)) {
((status = self->open()) != SOCK_SUCCESS)) {
Fw::Logger::logMsg("[WARNING] Failed to open port with status %d and errno %d\n", status, errno);
Os::Task::delay(SOCKET_RETRY_INTERVAL_MS);
}

View File

@ -133,6 +133,11 @@ class SocketReadTask {
*/
virtual void sendBuffer(Fw::Buffer buffer, SocketIpStatus status) = 0;
/**
* \brief called when the IPv4 system has been connected
*/
virtual void connected() = 0;
/**
* \brief a task designed to read from the socket and output incoming data
*

View File

@ -36,6 +36,7 @@
#endif
#include <string.h>
#include <new>
namespace Drv {
@ -49,7 +50,9 @@ struct SocketState {
}
};
UdpSocket::UdpSocket() : IpSocket(), m_state(new SocketState), m_recv_port(0) {}
UdpSocket::UdpSocket() : IpSocket(), m_state(new(std::nothrow) SocketState), m_recv_port(0) {
FW_ASSERT(m_state != NULL);
}
UdpSocket::~UdpSocket() {
FW_ASSERT(m_state);

View File

@ -161,7 +161,7 @@ section.
In order to start the receiving thread a call to the `Drv::SocketReadTask::startSocketTask` method is performed passing
in a name, and all arguments to `Os::Task::start` to start the task. An optional parameter, reconnect, will determine if
this read task will reconnect to sockets should a disconnect or error occur. Once started the read task will continue
this read task will reconnect to sockets should a disconnect or error occur. Once started the read task will continue
until a `Drv::SocketReadTask::stopSocketTask` has been called or an error occurred when started without reconnect set to
`true`. Once the socket stop call has been made, the user should call `Drv::SocketReadTask::joinSocketTask` in order to
wait until the full task has finished. `Drv::SocketReadTask::stopSocketTask` will call `Drv::IpSocket::close` on the
@ -169,7 +169,7 @@ provided Drv::IpSocket to ensure that the any blocking reads exit freeing the th
a Drv::SocketReadTask derived class is shown below.
```c++
Fw::EightyCharString name("ReceiveTask");
Os::TaskString name("ReceiveTask");
uplinkComm.startSocketTask(name, 100, 10 * 1024); // Default reconnect=true
...
@ -219,4 +219,4 @@ Further information can be read by referencing the following components.
`Drv::TcpClientComponent`: a F´ component wrapper of the tcp client
`Drv::TcpServerComponent`: a F´ component wrapper of the tcp server
`Drv::UdpComponent`: a F´ component wrapper of the udp
`Drv::UdpComponent`: a F´ component wrapper of the udp

View File

@ -13,7 +13,7 @@
#include <Drv/LinuxSerialDriver/LinuxSerialDriverComponentImpl.hpp>
#include "Fw/Types/BasicTypes.hpp"
#include <Fw/Types/EightyCharString.hpp>
#include <Os/TaskString.hpp>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
@ -400,7 +400,7 @@ namespace Drv {
void LinuxSerialDriverComponentImpl ::
startReadThread(NATIVE_INT_TYPE priority, NATIVE_INT_TYPE stackSize, NATIVE_INT_TYPE cpuAffinity) {
Fw::EightyCharString task("SerReader");
Os::TaskString task("SerReader");
Os::Task::TaskStatus stat = this->m_readTask.start(task, 0, priority, stackSize,
serialReadTaskEntry, this, cpuAffinity);
FW_ASSERT(stat == Os::Task::TASK_OK, stat);

View File

@ -15,7 +15,7 @@
#include <Fw/Logger/Logger.hpp>
#include "Fw/Types/BasicTypes.hpp"
#include <Fw/Types/Assert.hpp>
#include <Fw/Types/EightyCharString.hpp>
#include <Os/TaskString.hpp>
#include <Os/Log.hpp>
namespace Drv {
@ -101,7 +101,7 @@ namespace Drv {
NATIVE_INT_TYPE cpuAffinity
)
{
Fw::EightyCharString name("IpSocketRead");
Os::TaskString name("IpSocketRead");
// Do not restart task
if (not m_recvTask.isStarted()) {
this->configure(host,port);

View File

@ -0,0 +1,17 @@
// ======================================================================
// TcpClient.hpp
// Standardization header for TcpClient
// ======================================================================
#ifndef Drv_TcpClient_HPP
#define Drv_TcpClient_HPP
#include "Drv/TcpClient/TcpClientComponentImpl.hpp"
namespace Drv {
using TcpClient = TcpClientComponentImpl;
}
#endif

View File

@ -54,6 +54,13 @@ void TcpClientComponentImpl::sendBuffer(Fw::Buffer buffer, SocketIpStatus status
this->recv_out(0, buffer, (status == SOCK_SUCCESS) ? RecvStatus::RECV_OK : RecvStatus::RECV_ERROR);
}
void TcpClientComponentImpl::connected() {
if (isConnected_ready_OutputPort(0)) {
this->ready_out(0);
}
}
// ----------------------------------------------------------------------
// Handler implementations for user-defined typed input ports
// ----------------------------------------------------------------------

View File

@ -103,6 +103,12 @@ class TcpClientComponentImpl : public ByteStreamDriverModelComponentBase, public
*/
void sendBuffer(Fw::Buffer buffer, SocketIpStatus status);
/**
* \brief called when the IPv4 system has been connected
*/
void connected();
PRIVATE:
// ----------------------------------------------------------------------

View File

@ -51,7 +51,7 @@ bool constructApp(bool dump, U32 port_number, char* hostname) {
comm.init(0);
...
if (hostname != NULL && port_number != 0) {
Fw::EightyCharString name("ReceiveTask");
Os::TaskString name("ReceiveTask");
comm.configure(hostname, port_number);
comm.startSocketTask(name, TASK_PRIORITY, TASK_STACK_SIZE);
}

View File

@ -43,7 +43,7 @@ void Tester ::test_with_loop(U32 iterations, bool recv_thread) {
// Start up a receive thread
if (recv_thread) {
Fw::EightyCharString name("receiver thread");
Os::TaskString name("receiver thread");
this->component.startSocketTask(name, 50, 1024, true);
}
@ -85,14 +85,17 @@ void Tester ::test_with_loop(U32 iterations, bool recv_thread) {
while (not m_spinner) {}
}
}
this->component.close();
// Properly stop the client on the last iteration
if ((1 + i) == iterations && recv_thread) {
this->component.stopSocketTask();
this->component.joinSocketTask(NULL);
} else {
this->component.close();
}
server.close();
}
// Wait for the receiver to shutdown
if (recv_thread) {
this->component.stopSocketTask();
this->component.joinSocketTask(NULL);
}
server.shutdown();
ASSERT_from_ready_SIZE(iterations);
}
Tester ::Tester()
@ -146,6 +149,10 @@ void Tester ::test_advanced_reconnect() {
delete[] recvBuffer.getData();
}
void Tester ::from_ready_handler(const NATIVE_INT_TYPE portNum) {
this->pushFromPortEntry_ready();
}
Fw::Buffer Tester ::
from_allocate_handler(
const NATIVE_INT_TYPE portNum,
@ -193,6 +200,12 @@ Fw::Buffer Tester ::
this->get_from_recv(0)
);
// recv
this->component.set_ready_OutputPort(
0,
this->get_from_ready(0)
);
// allocate
this->component.set_allocate_OutputPort(
0,

View File

@ -69,6 +69,12 @@ namespace Drv {
RecvStatus recvStatus
);
//! Handler for from_ready
//!
void from_ready_handler(
const NATIVE_INT_TYPE portNum /*!< The port number*/
);
//! Handler for from_allocate
//!
Fw::Buffer from_allocate_handler(

View File

@ -60,6 +60,13 @@ void TcpServerComponentImpl::sendBuffer(Fw::Buffer buffer, SocketIpStatus status
this->recv_out(0, buffer, (status == SOCK_SUCCESS) ? RecvStatus::RECV_OK : RecvStatus::RECV_ERROR);
}
void TcpServerComponentImpl::connected() {
if (isConnected_ready_OutputPort(0)) {
this->ready_out(0);
}
}
// ----------------------------------------------------------------------
// Handler implementations for user-defined typed input ports
// ----------------------------------------------------------------------

View File

@ -123,6 +123,12 @@ class TcpServerComponentImpl : public ByteStreamDriverModelComponentBase, public
*/
void sendBuffer(Fw::Buffer buffer, SocketIpStatus status);
/**
* \brief called when the IPv4 system has been connected
*/
void connected();
PRIVATE:
// ----------------------------------------------------------------------

View File

@ -57,7 +57,7 @@ bool constructApp(bool dump, U32 port_number, char* hostname) {
comm.init(0);
...
if (hostname != NULL && port_number != 0) {
Fw::EightyCharString name("ReceiveTask");
Os::TaskString name("ReceiveTask");
comm.configure(hostname, port_number);
comm.startup();
comm.startSocketTask(name, TASK_PRIORITY, TASK_STACK_SIZE);

View File

@ -42,7 +42,7 @@ void Tester ::test_with_loop(U32 iterations, bool recv_thread) {
// Start up a receive thread
if (recv_thread) {
Fw::EightyCharString name("receiver thread");
Os::TaskString name("receiver thread");
this->component.startSocketTask(name, 50, 1024, true);
}
@ -88,15 +88,17 @@ void Tester ::test_with_loop(U32 iterations, bool recv_thread) {
while (not m_spinner) {}
}
}
this->component.close();
client.close();
}
// Wait for the receiver to shutdown
if (recv_thread) {
this->component.shutdown();
this->component.stopSocketTask();
this->component.joinSocketTask(NULL);
client.close(); // Client must be closed first or the server risks binding to an existing address
// Properly stop the client on the last iteration
if ((1 + i) == iterations && recv_thread) {
this->component.shutdown();
this->component.stopSocketTask();
this->component.joinSocketTask(NULL);
} else {
this->component.close();
}
}
ASSERT_from_ready_SIZE(iterations);
}
Tester ::Tester()
@ -143,6 +145,10 @@ void Tester ::from_recv_handler(const NATIVE_INT_TYPE portNum, Fw::Buffer& recvB
delete[] recvBuffer.getData();
}
void Tester ::from_ready_handler(const NATIVE_INT_TYPE portNum) {
this->pushFromPortEntry_ready();
}
Fw::Buffer Tester ::
from_allocate_handler(
const NATIVE_INT_TYPE portNum,
@ -190,6 +196,12 @@ void Tester ::
this->get_from_recv(0)
);
// recv
this->component.set_ready_OutputPort(
0,
this->get_from_ready(0)
);
// allocate
this->component.set_allocate_OutputPort(
0,

Some files were not shown because too many files have changed in this diff Show More