/** * Read and fill the Variable $variable with its value contained * in the current stream. * * @param Variable $variable A QTI Runtime Variable object. * @throws BinaryStreamAccessException If an error occurs at the binary level. */ public function readVariableValue(Variable $variable) { try { $isNull = $this->readBoolean(); if ($isNull === true) { // Nothing more to be read. $variable->setValue(null); return; } $count = $this->readBoolean() === true ? 1 : $this->readShort(); $cardinality = $variable->getCardinality(); $baseType = $variable->getBaseType(); if ($cardinality === Cardinality::RECORD) { // Deal with records. $values = new RecordContainer(); for ($i = 0; $i < $count; $i++) { $isNull = $this->readBoolean(); $val = $this->readRecordField($isNull); $values[$val[0]] = $val[1]; } $variable->setValue($values); } else { $toCall = 'read' . ucfirst(BaseType::getNameByConstant($baseType)); if ($cardinality === Cardinality::SINGLE) { // Deal with a single value. $variable->setValue(Utils::valueToRuntime(call_user_func(array($this, $toCall)), $baseType)); } else { // Deal with multiple values. $values = $cardinality === Cardinality::MULTIPLE ? new MultipleContainer($baseType) : new OrderedContainer($baseType); for ($i = 0; $i < $count; $i++) { $isNull = $this->readBoolean(); $values[] = $isNull === true ? null : Utils::valueToRuntime(call_user_func(array($this, $toCall)), $baseType); } $variable->setValue($values); } } } catch (BinaryStreamAccessException $e) { $msg = "An error occured while reading a Variable value."; throw new QtiBinaryStreamAccessException($msg, $this, QtiBinaryStreamAccessException::VARIABLE, $e); } catch (InvalidArgumentException $e) { $msg = "Datatype mismatch for variable '{$varId}'."; throw new QtiBinaryStreamAccessException($msg, $this, QtiBinaryStreamAccessException::VARIABLE, $e); } }