Skip to content

Commit ed3a2c5

Browse files
committed
Revisit long string initialisation
Also a bit of tidying of device.py
1 parent 0df634e commit ed3a2c5

File tree

2 files changed

+31
-42
lines changed

2 files changed

+31
-42
lines changed

softioc/builder.py

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -182,31 +182,25 @@ def WaveformOut(name, *value, **fields):
182182
return PythonDevice.waveform_out(name, **fields)
183183

184184

185-
def _long_string(value, fields):
186-
if 'initial_value' in fields:
187-
assert not value, 'Can\'t specify initial value twice!'
188-
value = (fields.pop('initial_value'),)
189-
190-
if value:
191-
# If a value is specified it should be the *only* non keyword
192-
# argument.
193-
value, = value
194-
fields['initial_value'] = value
195-
length = len(value)
196-
else:
197-
# No value specified, so require length and datatype to be specified.
185+
def _long_string(fields):
186+
if 'length' in fields:
198187
length = fields.pop('length')
188+
elif 'initial_value' in fields:
189+
length = len(fields['initial_value'].encode(errors = 'replace')) + 1
190+
else:
191+
# Default length of 256
192+
length = 256
199193

200194
fields['NELM'] = length
201195
fields['FTVL'] = 'UCHAR'
202196

203197

204-
def longStringIn(name, *value, **fields):
205-
_long_string(value, fields)
198+
def longStringIn(name, **fields):
199+
_long_string(fields)
206200
return _in_record('long_stringin', name, **fields)
207201

208-
def longStringOut(name, *value, **fields):
209-
_long_string(value, fields)
202+
def longStringOut(name, **fields):
203+
_long_string(fields)
210204
return PythonDevice.long_stringout(name, **fields)
211205

212206

softioc/device.py

Lines changed: 20 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -323,35 +323,35 @@ class WaveformBase(ProcessDeviceSupportCore):
323323
# NORD Currently reported length of array (0 <= NORD <= NELM)
324324
_fields_ = ['UDF', 'FTVL', 'BPTR', 'NELM', 'NORD']
325325
# Allow set() to be called before init_record:
326-
dtype = None
326+
_dtype = None
327327

328328
def _default_value(self):
329329
return numpy.array([])
330330

331331
def init_record(self, record):
332332
self._nelm = record.NELM
333333
self._dbf_type_ = record.FTVL
334-
self.dtype = fields.DbfCodeToNumpy[record.FTVL]
334+
self._dtype = fields.DbfCodeToNumpy[record.FTVL]
335335
return self.__super.init_record(record)
336336

337337
def _read_value(self, record):
338338
nord = record.NORD
339-
result = numpy.empty(nord, dtype = self.dtype)
339+
result = numpy.empty(nord, dtype = self._dtype)
340340
memmove(
341341
result.ctypes.data_as(c_void_p), record.BPTR,
342-
self.dtype.itemsize * nord)
342+
self._dtype.itemsize * nord)
343343
return result
344344

345345
def _write_value(self, record, value):
346-
value = numpy.require(value, dtype = self.dtype)
346+
value = numpy.require(value, dtype = self._dtype)
347347

348348
nelm = record.NELM
349349
nord = len(value)
350350
if nord > nelm:
351351
nord = nelm
352352
memmove(
353353
record.BPTR, value.ctypes.data_as(c_void_p),
354-
self.dtype.itemsize * nord)
354+
self._dtype.itemsize * nord)
355355
record.NORD = nord
356356

357357
def _compare_values(self, value, other):
@@ -360,7 +360,7 @@ def _compare_values(self, value, other):
360360
def _value_to_epics(self, value):
361361
# Ensure we always convert incoming value into numpy array, regardless
362362
# of whether the record has been initialised or not
363-
value = numpy.require(value, dtype = self.dtype)
363+
value = numpy.require(value, dtype = self._dtype)
364364
if value.shape == ():
365365
value.shape = (1,)
366366
assert value.ndim == 1, 'Can\'t write multidimensional arrays'
@@ -379,7 +379,7 @@ def _epics_to_value(self, value):
379379
return value
380380

381381
def _value_to_dbr(self, value):
382-
value = numpy.require(value, dtype = self.dtype)
382+
value = numpy.require(value, dtype = self._dtype)
383383
return self._dbf_type_, len(value), value.ctypes.data, value
384384

385385

@@ -392,26 +392,21 @@ class waveform_out(WaveformBase, ProcessDeviceSupportOut):
392392
_device_name_ = 'devPython_waveform_out'
393393

394394

395-
# Convert string into numpy array of char
396-
def encode_string(value, length = None):
397-
value = value.encode(errors = 'replace')
398-
# Convert a string into an array of characters. This will produce
399-
# the correct behaviour when treating a character array as a string.
400-
# Note that the trailing null is needed to work around problems with
401-
# some clients.
402-
value = numpy.frombuffer(value + b'\0', dtype = numpy.uint8)
403-
404-
# Truncate value to fit
405-
if length:
406-
value = value[:length]
407-
return value
408-
409-
410395
class LongStringBase(WaveformBase):
411-
dtype = numpy.dtype('uint8')
396+
_dtype = numpy.dtype('uint8')
412397

413398
def _value_to_epics(self, value):
414-
return encode_string(value, getattr(self, '_nelm', None))
399+
value = value.encode(errors = 'replace')
400+
# Convert a string into an array of characters. This will produce
401+
# the correct behaviour when treating a character array as a string.
402+
# Note that the trailing null is needed to work around problems with
403+
# some clients.
404+
value = numpy.frombuffer(value + b'\0', dtype = numpy.uint8)
405+
406+
# Truncate value to fit
407+
if hasattr(self, '_nelm'):
408+
value = value[:self._nelm]
409+
return value
415410

416411
def _epics_to_value(self, value):
417412
return _string_at(value.ctypes, len(value))

0 commit comments

Comments
 (0)