diff --git a/src/Buffer.php b/src/Buffer.php index bd3b581..3751ebe 100644 --- a/src/Buffer.php +++ b/src/Buffer.php @@ -173,7 +173,7 @@ public function readString($length, $round = 0, $charset = null) $charsetFrom = isset($this->charset) ? $this->charset : mb_internal_encoding(); $charsetTo = isset($charset) ? $charset : mb_internal_encoding(); if (isset($str) && (strtolower($charsetFrom) != strtolower($charsetTo))) { - $str = mb_convert_encoding($str, $charsetTo, $this->charset); + $str = mb_convert_encoding($str, $charsetTo, $charsetFrom); } return $str; @@ -213,7 +213,26 @@ public function read($length = null) } /** - * @param $data + * @param string $data + * @param int $maxLength + * + * @return int + */ + public function lengthBytes($data, $maxLength = null, $charset = null) + { + $charsetTo = isset($this->charset) ? $this->charset : mb_internal_encoding(); + $charsetFrom = isset($charset) ? $charset : mb_internal_encoding(); + if (isset($data) && (strtolower($charsetTo) != strtolower($charsetFrom))) { + $data = mb_convert_encoding($data, $charsetTo, $charsetFrom); + } + if (isset($data) && isset($maxLength)) { + $data = mb_strcut($data, 0, $maxLength, $charsetTo); + } + return \strlen($data); + } + + /** + * @param string $data * @param int|string $length * @param null $charset * @@ -226,7 +245,9 @@ public function writeString($data, $length = '*', $charset = null) if (isset($data) && (strtolower($charsetFrom) != strtolower($charsetTo))) { $data = mb_convert_encoding($data, $charsetTo, $charsetFrom); } - //file_put_contents("/var/encuestas/test.txt", "To: " . $charsetTo . " FROM:" . $charsetFrom . "\n", FILE_APPEND | LOCK_EX); + if (isset($length) && ($length != '*')) { + $data = mb_strcut($data, 0, $length, $charsetTo); + } return $this->write(pack('A' . $length, $data)); } diff --git a/src/Sav/Record/Info/LongStringValueLabels.php b/src/Sav/Record/Info/LongStringValueLabels.php index e804588..5fcb696 100644 --- a/src/Sav/Record/Info/LongStringValueLabels.php +++ b/src/Sav/Record/Info/LongStringValueLabels.php @@ -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); } } diff --git a/src/Sav/Record/Info/VariableAttributes.php b/src/Sav/Record/Info/VariableAttributes.php index 46a90b2..5a1e088 100644 --- a/src/Sav/Record/Info/VariableAttributes.php +++ b/src/Sav/Record/Info/VariableAttributes.php @@ -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); } diff --git a/src/Sav/Record/ValueLabel.php b/src/Sav/Record/ValueLabel.php index 8ef3ae0..900c539 100644 --- a/src/Sav/Record/ValueLabel.php +++ b/src/Sav/Record/ValueLabel.php @@ -97,22 +97,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. diff --git a/src/Sav/Record/Variable.php b/src/Sav/Record/Variable.php index 3ae6eb8..cd8f7ee 100644 --- a/src/Sav/Record/Variable.php +++ b/src/Sav/Record/Variable.php @@ -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 @@ -181,7 +174,6 @@ public function write(Buffer $buffer) $buffer->writeInt($format); // Print format $buffer->writeInt($format); // Write format $buffer->writeString($this->getSegmentName($i - 1), 8); - $this->writeBlank($buffer, $segmentWidth); } } @@ -222,6 +214,6 @@ public function getSegmentName($seg = 0) return mb_strtoupper($this->name); } $sufix = str_pad($str, 2, "_", STR_PAD_LEFT); - return mb_strtoupper(mb_substr($this->name.$sufix, 0, 8)); + return mb_strtoupper(mb_strcut($this->name.$sufix, 0, 8)); } }