Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Improve the required bytes calculation. #72

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 21 additions & 2 deletions src/Buffer.php
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,24 @@ public function read($length = null)
}

/**
* @param $data
* @param string $data
* @param int $maxLength
*
* @return int
*/
public function lengthBytes($data, $maxLength = null)
{
if (strtolower($this->streamCharset) != strtolower($this->systemCharset)) {
$data = mb_convert_encoding($data, $this->streamCharset, $this->systemCharset);
}
if (isset($maxLength)) {
$data = mb_strcut($data, 0, $maxLength, $this->streamCharset);
}
return \strlen($data);
}

/**
* @param string $data
* @param int|string $length
*
* @return false|int
Expand All @@ -224,7 +241,9 @@ public function writeString($data, $length = '*')
if (strtolower($this->streamCharset) != strtolower($this->systemCharset)) {
$data = mb_convert_encoding($data, $this->streamCharset, $this->systemCharset);
}

if (isset($length) && ($length != '*')) {
$data = mb_strcut($data, 0, $length, $this->streamCharset);
}
return $this->write(pack('A' . $length, $data));
}

Expand Down
10 changes: 6 additions & 4 deletions src/Sav/Record/Info/LongStringValueLabels.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,17 @@ public function write(Buffer $buffer)
throw new \InvalidArgumentException('values required');
}
$width = (int) $data['width'];
$localBuffer->writeInt(mb_strlen($varName));
$localBuffer->writeString($varName, mb_strlen($varName));
$varLengthBytes = $buffer->lengthBytes($varName);
$localBuffer->writeInt($varLengthBytes);
$localBuffer->writeString($varName, $varLengthBytes);
$localBuffer->writeInt($width);
$localBuffer->writeInt(Utils::is_countable($data['values']) ? \count($data['values']) : 0);
foreach ($data['values'] as $value => $label) {
$localBuffer->writeInt($width);
$localBuffer->writeString($value, $width);
$localBuffer->writeInt(mb_strlen($label));
$localBuffer->writeString($label, mb_strlen($label));
$labelLengthBytes = $buffer->lengthBytes($label);
$localBuffer->writeInt($labelLengthBytes);
$localBuffer->writeString($label, $labelLengthBytes);
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/Sav/Record/Info/VariableAttributes.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public function write(Buffer $buffer)

if ($lines !== []) {
$data = implode('/', $lines);
$this->dataCount = mb_strlen($data);
$this->dataCount = \strlen($data);
parent::write($buffer);
$buffer->writeString($data);
}
Expand Down
14 changes: 4 additions & 10 deletions src/Sav/Record/ValueLabel.php
Original file line number Diff line number Diff line change
Expand Up @@ -96,22 +96,16 @@ public function write(Buffer $buffer)
$buffer->writeInt(self::TYPE);
$buffer->writeInt(\count($this->labels));
foreach ($this->labels as $item) {
$labelLength = min(mb_strlen($item['label']), self::LABEL_MAX_LENGTH);
$label = mb_substr($item['label'], 0, $labelLength);
$labelLengthBytes = mb_strlen($label, '8bit');
while ($labelLengthBytes > 255) {
// Strip one char, can be multiple bytes
$label = mb_substr($label, 0, -1);
$labelLengthBytes = mb_strlen($label, '8bit');
}

$labelLengthBytes = $buffer->lengthBytes($item['label'], self::LABEL_MAX_LENGTH);
$labelLengthBytesRound = Utils::roundUp($labelLengthBytes + 1, 8) - 1;

if ($convertToDouble) {
$item['value'] = Utils::stringToDouble($item['value']);
}

$buffer->writeDouble($item['value']);
$buffer->write(\chr($labelLengthBytes));
$buffer->writeString($label, Utils::roundUp($labelLengthBytes + 1, 8) - 1);
$buffer->writeString($item['label'], $labelLengthBytesRound);
}

// Value label variable record.
Expand Down
23 changes: 8 additions & 15 deletions src/Sav/Record/Variable.php
Original file line number Diff line number Diff line change
Expand Up @@ -141,17 +141,10 @@ public function write(Buffer $buffer)
$buffer->writeString($this->name, 8);

if ($hasLabel) {
// Maxlength is 255 bytes, since we write utf8 a char can be multiple bytes
$labelLength = min(mb_strlen($this->label), 255);
$label = mb_substr($this->label, 0, $labelLength);
$labelLengthBytes = mb_strlen($label, '8bit');
while ($labelLengthBytes > 255) {
// Strip one char, can be multiple bytes
$label = mb_substr($label, 0, -1);
$labelLengthBytes = mb_strlen($label, '8bit');
}
$labelLengthBytes = $buffer->lengthBytes($this->label, self::REAL_VLS_CHUNK);
$labelLengthBytesRound = Utils::roundUp($labelLengthBytes, 4);
$buffer->writeInt($labelLengthBytes);
$buffer->writeString($label, Utils::roundUp($labelLengthBytes, 4));
$buffer->writeString($this->label, $labelLengthBytesRound);
}

// TODO: test
Expand Down Expand Up @@ -180,10 +173,10 @@ public function write(Buffer $buffer)
$buffer->writeInt(0); // No missing values
$buffer->writeInt($format); // Print format
$buffer->writeInt($format); // Write format
$buffer->writeString($this->getSegmentName($i - 1), 8);
$buffer->writeString($this->getSegmentName($buffer, $i - 1), 8);
if ($hasLabel) {
$buffer->writeInt($labelLengthBytes);
$buffer->writeString($label, Utils::roundUp($labelLengthBytes, 4));
$buffer->writeString($this->label, Utils::roundUp($labelLengthBytes, 4));
}

$this->writeBlank($buffer, $segmentWidth);
Expand Down Expand Up @@ -215,13 +208,13 @@ public function writeBlank(Buffer $buffer, $width)
*
* @return string
*/
public function getSegmentName($seg = 0)
public function getSegmentName($buffer, $seg = 0)
{
// TODO: refactory
$name = $this->name;
$name = mb_substr($name, 0, 6);
$name = mb_strcut($name, 0, 6, $buffer->systemCharset);
$name .= $seg;

return mb_strtoupper($name);
return mb_strtoupper($name, $buffer->systemCharset);
}
}