diff --git a/poincare/include/poincare/tree_node.h b/poincare/include/poincare/tree_node.h index 36290867b..667e7a722 100644 --- a/poincare/include/poincare/tree_node.h +++ b/poincare/include/poincare/tree_node.h @@ -82,6 +82,7 @@ public: virtual void didAddChildAtIndex(int newNumberOfChildren) {} // Serialization + // Return the number of chars written, without the null-terminating char. virtual int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { assert(false); return 0; } /* When serializing, we turn a tree into a string. In order not to lose * structure information, we sometimes need to add system parentheses (that diff --git a/poincare/src/constant.cpp b/poincare/src/constant.cpp index 9d13524cd..a02d89df1 100644 --- a/poincare/src/constant.cpp +++ b/poincare/src/constant.cpp @@ -14,6 +14,8 @@ namespace Poincare { +static inline int minInt(int x, int y) { return x < y ? x : y; } + ConstantNode::ConstantNode(const char * newName, int length) : SymbolAbstractNode() { strlcpy(const_cast(name()), newName, length+1); } @@ -66,7 +68,7 @@ int ConstantNode::serialize(char * buffer, int bufferSize, Preferences::PrintFlo if (bufferSize == 0) { return -1; } - return strlcpy(buffer, m_name, bufferSize); + return minInt(strlcpy(buffer, m_name, bufferSize), bufferSize - 1); } template diff --git a/poincare/src/decimal.cpp b/poincare/src/decimal.cpp index bbc38eef8..2ffd0f477 100644 --- a/poincare/src/decimal.cpp +++ b/poincare/src/decimal.cpp @@ -109,11 +109,11 @@ int DecimalNode::convertToText(char * buffer, int bufferSize, Preferences::Print return -1; } buffer[bufferSize-1] = 0; - int currentChar = 0; - if (currentChar >= bufferSize-1) { return bufferSize-1; } + if (bufferSize == 1) { + return 0; + } if (unsignedMantissa().isZero()) { - currentChar += SerializationHelper::CodePoint(buffer + currentChar, bufferSize - currentChar, '0'); // This already writes the null terminating char - return currentChar; + return SerializationHelper::CodePoint(buffer, bufferSize, '0'); // This already writes the null terminating char } int exponent = m_exponent; char tempBuffer[PrintFloat::k_numberOfStoredSignificantDigits+1]; @@ -135,6 +135,7 @@ int DecimalNode::convertToText(char * buffer, int bufferSize, Preferences::Print * to 2000. To avoid printing 2.000, we removeZeroAtTheEnd here. */ removeZeroAtTheEnd(&m); } + int currentChar = 0; if (m_negative) { currentChar += SerializationHelper::CodePoint(buffer + currentChar, bufferSize - currentChar, '-'); if (currentChar >= bufferSize-1) { return bufferSize-1; } diff --git a/poincare/src/factorial.cpp b/poincare/src/factorial.cpp index 38afca245..7d2cafddc 100644 --- a/poincare/src/factorial.cpp +++ b/poincare/src/factorial.cpp @@ -77,8 +77,7 @@ int FactorialNode::serialize(char * buffer, int bufferSize, Preferences::PrintFl if ((numberOfChar < 0) || (numberOfChar >= bufferSize-1)) { return numberOfChar; } - numberOfChar += SerializationHelper::CodePoint(&buffer[numberOfChar], bufferSize-numberOfChar, '!'); - buffer[numberOfChar] = 0; + numberOfChar += SerializationHelper::CodePoint(buffer+numberOfChar, bufferSize-numberOfChar, '!'); return numberOfChar; } diff --git a/poincare/src/fraction_layout.cpp b/poincare/src/fraction_layout.cpp index da365de34..ab9bb044d 100644 --- a/poincare/src/fraction_layout.cpp +++ b/poincare/src/fraction_layout.cpp @@ -123,8 +123,7 @@ int FractionLayoutNode::serialize(char * buffer, int bufferSize, Preferences::Pr return -1; } buffer[bufferSize-1] = 0; - int numberOfChar = 0; - if (numberOfChar >= bufferSize-1) { return bufferSize-1;} + if (bufferSize == 1) { return 0;} /* Add System parenthesis to detect omitted multiplication: * 2 @@ -133,8 +132,8 @@ int FractionLayoutNode::serialize(char * buffer, int bufferSize, Preferences::Pr */ // Add system parenthesis - numberOfChar+= SerializationHelper::CodePoint(buffer + numberOfChar, bufferSize - numberOfChar, UCodePointLeftSystemParenthesis); - if (numberOfChar >= bufferSize-1) { return bufferSize-1;} + int numberOfChar = SerializationHelper::CodePoint(buffer, bufferSize, UCodePointLeftSystemParenthesis); + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } // Write the content of the fraction numberOfChar += SerializationHelper::Infix(this, buffer+numberOfChar, bufferSize-numberOfChar, floatDisplayMode, numberOfSignificantDigits, "/"); @@ -142,9 +141,6 @@ int FractionLayoutNode::serialize(char * buffer, int bufferSize, Preferences::Pr // Add system parenthesis numberOfChar+= SerializationHelper::CodePoint(buffer + numberOfChar, bufferSize - numberOfChar, UCodePointRightSystemParenthesis); - if (numberOfChar >= bufferSize-1) { return bufferSize-1;} - - buffer[numberOfChar] = 0; return numberOfChar; } diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index a28e19e0b..431c19697 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -174,32 +174,32 @@ int Integer::serialize(char * buffer, int bufferSize) const { abs.setNegative(false); IntegerDivision d = udiv(abs, base); - int size = 0; + int length = 0; if (isZero()) { - size += SerializationHelper::CodePoint(buffer + size, bufferSize - size, '0'); + length += SerializationHelper::CodePoint(buffer + length, bufferSize - length, '0'); } else if (isNegative()) { - size += SerializationHelper::CodePoint(buffer + size, bufferSize - size, '-'); + length += SerializationHelper::CodePoint(buffer + length, bufferSize - length, '-'); } while (!(d.remainder.isZero() && d.quotient.isZero())) { char c = char_from_digit(d.remainder.isZero() ? 0 : d.remainder.digit(0)); - if (size >= bufferSize-1) { + if (length >= bufferSize-1) { return PrintFloat::convertFloatToText(NAN, buffer, bufferSize, PrintFloat::k_numberOfStoredSignificantDigits, Preferences::PrintFloatMode::Decimal); } - size += SerializationHelper::CodePoint(buffer + size, bufferSize - size, c); + length += SerializationHelper::CodePoint(buffer + length, bufferSize - length, c); d = udiv(d.quotient, base); } - assert(size <= bufferSize - 1); - buffer[size] = 0; + assert(length <= bufferSize - 1); + buffer[length] = 0; // Flip the string - for (int i = m_negative, j=size-1 ; i < j ; i++, j--) { + for (int i = m_negative, j=length-1 ; i < j ; i++, j--) { char c = buffer[i]; buffer[i] = buffer[j]; buffer[j] = c; } - return size; + return length; } // Layout diff --git a/poincare/src/integral_layout.cpp b/poincare/src/integral_layout.cpp index f3cdd7ce0..862b22ccd 100644 --- a/poincare/src/integral_layout.cpp +++ b/poincare/src/integral_layout.cpp @@ -202,7 +202,6 @@ int IntegralLayoutNode::serialize(char * buffer, int bufferSize, Preferences::Pr // Write the closing system parenthesis numberOfChar += SerializationHelper::CodePoint(buffer + numberOfChar, bufferSize - numberOfChar, UCodePointRightSystemParenthesis); - buffer[numberOfChar] = 0; return numberOfChar; } diff --git a/poincare/src/matrix.cpp b/poincare/src/matrix.cpp index 5d3778733..377255f2a 100644 --- a/poincare/src/matrix.cpp +++ b/poincare/src/matrix.cpp @@ -17,6 +17,8 @@ namespace Poincare { +static inline int minInt(int x, int y) { return x < y ? x : y; } + void MatrixNode::didAddChildAtIndex(int newNumberOfChildren) { setNumberOfRows(1); setNumberOfColumns(newNumberOfChildren); @@ -41,11 +43,10 @@ int MatrixNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloat return -1; } buffer[bufferSize-1] = 0; - int currentChar = 0; - if (currentChar >= bufferSize-1) { + if (bufferSize == 1) { return 0; } - currentChar += SerializationHelper::CodePoint(buffer + currentChar, bufferSize - currentChar, '['); + int currentChar = SerializationHelper::CodePoint(buffer, bufferSize, '['); if (currentChar >= bufferSize-1) { return currentChar; } @@ -78,11 +79,7 @@ int MatrixNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloat } } currentChar += SerializationHelper::CodePoint(buffer + currentChar, bufferSize - currentChar, ']'); - if (currentChar >= bufferSize-1) { - return currentChar; - } - buffer[currentChar] = 0; - return currentChar; + return minInt(currentChar, bufferSize-1); } template diff --git a/poincare/src/matrix_layout.cpp b/poincare/src/matrix_layout.cpp index d390eea1e..de2ed5e93 100644 --- a/poincare/src/matrix_layout.cpp +++ b/poincare/src/matrix_layout.cpp @@ -7,6 +7,8 @@ namespace Poincare { +static inline int minInt(int x, int y) { return x < y ? x : y; } + // MatrixLayoutNode void MatrixLayoutNode::addGreySquares() { @@ -98,10 +100,9 @@ int MatrixLayoutNode::serialize(char * buffer, int bufferSize, Preferences::Prin } buffer[bufferSize-1] = 0; if (bufferSize == 1) { - return 1; + return 0; } - int numberOfChar = 0; - numberOfChar += SerializationHelper::CodePoint(buffer + numberOfChar, bufferSize - numberOfChar, '['); + int numberOfChar = SerializationHelper::CodePoint(buffer, bufferSize, '['); if (numberOfChar >= bufferSize-1) { return bufferSize-1;} int maxRowIndex = hasGreySquares() ? m_numberOfRows - 1 : m_numberOfRows; @@ -117,9 +118,7 @@ int MatrixLayoutNode::serialize(char * buffer, int bufferSize, Preferences::Prin if (numberOfChar >= bufferSize-1) { return bufferSize-1; } } numberOfChar += SerializationHelper::CodePoint(buffer + numberOfChar, bufferSize - numberOfChar, ']'); - if (numberOfChar >= bufferSize-1) { return bufferSize-1; } - buffer[numberOfChar] = 0; - return numberOfChar; + return minInt(numberOfChar, bufferSize-1); } // Protected diff --git a/poincare/src/opposite.cpp b/poincare/src/opposite.cpp index d2531dcf4..bdcba9716 100644 --- a/poincare/src/opposite.cpp +++ b/poincare/src/opposite.cpp @@ -56,14 +56,12 @@ int OppositeNode::serialize(char * buffer, int bufferSize, Preferences::PrintFlo return -1; } buffer[bufferSize-1] = 0; - int numberOfChar = 0; if (bufferSize == 1) { return 0; } - numberOfChar += SerializationHelper::CodePoint(buffer + numberOfChar, bufferSize - numberOfChar, '-'); + int numberOfChar = SerializationHelper::CodePoint(buffer, bufferSize, '-'); if (numberOfChar >= bufferSize - 1) { return bufferSize - 1; } numberOfChar += childAtIndex(0)->serialize(buffer+numberOfChar, bufferSize-numberOfChar, floatDisplayMode, numberOfSignificantDigits); - buffer[numberOfChar] = 0; return numberOfChar; } diff --git a/poincare/src/print_float.cpp b/poincare/src/print_float.cpp index 66fc4ad21..6fca595e9 100644 --- a/poincare/src/print_float.cpp +++ b/poincare/src/print_float.cpp @@ -59,6 +59,13 @@ void PrintFloat::Long::DivisionByTen(const Long & longToDivide, Long * quotient, } int PrintFloat::Long::serialize(char * buffer, int bufferSize) const { + if (bufferSize == 0) { + return -1; + } + buffer[bufferSize-1] = 0; + if (bufferSize == 1) { + return 0; + } int numberOfChars = m_negative ? 1 : 0; // 1 for the minus sign char if (m_digits[0] != 0) { numberOfChars += PrintInt::Left(m_digits[0], buffer + numberOfChars, bufferSize - numberOfChars - 1); diff --git a/poincare/src/rational.cpp b/poincare/src/rational.cpp index c4ed722a5..b4920e9ad 100644 --- a/poincare/src/rational.cpp +++ b/poincare/src/rational.cpp @@ -72,10 +72,10 @@ int RationalNode::serialize(char * buffer, int bufferSize, Preferences::PrintFlo } buffer[bufferSize-1] = 0; int numberOfChar = signedNumerator().serialize(buffer, bufferSize); - if (isInteger()) { + if (numberOfChar >= bufferSize-1) { return numberOfChar; } - if (numberOfChar >= bufferSize-1) { + if (isInteger()) { return numberOfChar; } numberOfChar += SerializationHelper::CodePoint(buffer + numberOfChar, bufferSize - numberOfChar, '/'); diff --git a/poincare/src/sequence_layout.cpp b/poincare/src/sequence_layout.cpp index 03f133357..e754fb98a 100644 --- a/poincare/src/sequence_layout.cpp +++ b/poincare/src/sequence_layout.cpp @@ -238,7 +238,6 @@ int SequenceLayoutNode::writeDerivedClassInBuffer(const char * operatorName, cha // Write the closing system parenthesis numberOfChar += SerializationHelper::CodePoint(buffer + numberOfChar, bufferSize - numberOfChar, UCodePointRightSystemParenthesis); - buffer[numberOfChar] = 0; return numberOfChar; } diff --git a/poincare/src/serialization_helper.cpp b/poincare/src/serialization_helper.cpp index ff922b997..cffe218cb 100644 --- a/poincare/src/serialization_helper.cpp +++ b/poincare/src/serialization_helper.cpp @@ -76,7 +76,7 @@ int SerializationHelper::SerializeChild( return bufferSize-1; } } - buffer[numberOfChar] = 0; + assert(buffer[numberOfChar] == 0); return numberOfChar; } @@ -114,7 +114,8 @@ int InfixPrefix( // Add the opening (system or user) parenthesis numberOfChar += UTF8Decoder::CodePointToChars(needsSystemParentheses ? UCodePointLeftSystemParenthesis : CodePoint('('), buffer+numberOfChar, bufferSize - numberOfChar); if (numberOfChar >= bufferSize-1) { - return bufferSize-1; + assert(buffer[bufferSize - 1] == 0); + return bufferSize - 1; } } @@ -134,7 +135,7 @@ int InfixPrefix( strlcpy(buffer+numberOfChar, operatorName, bufferSize-numberOfChar); if (numberOfChar >= bufferSize-1) { assert(buffer[bufferSize - 1] == 0); - return bufferSize-1; + return bufferSize - 1; } } // Write the child, with or without parentheses if needed @@ -143,26 +144,26 @@ int InfixPrefix( numberOfChar += UTF8Decoder::CodePointToChars(UCodePointLeftSystemParenthesis, buffer+numberOfChar, bufferSize - numberOfChar); if (numberOfChar >= bufferSize-1) { assert(buffer[bufferSize - 1] == 0); - return bufferSize-1; + return bufferSize - 1; } } numberOfChar += node->childAtIndex(i)->serialize(buffer+numberOfChar, bufferSize-numberOfChar, floatDisplayMode, numberOfDigits); if (numberOfChar >= bufferSize-1) { assert(buffer[bufferSize - 1] == 0); - return bufferSize-1; + return bufferSize - 1; } if (needsSystemParentheses && (childrenCount > 1)) { numberOfChar += UTF8Decoder::CodePointToChars(UCodePointRightSystemParenthesis, buffer+numberOfChar, bufferSize - numberOfChar); if (numberOfChar >= bufferSize-1) { assert(buffer[bufferSize - 1] == 0); - return bufferSize-1; + return bufferSize - 1; } } } else { numberOfChar += SerializationHelper::SerializeChild(node->childAtIndex(i), node, buffer + numberOfChar, bufferSize - numberOfChar, floatDisplayMode, numberOfDigits); if (numberOfChar >= bufferSize-1) { assert(buffer[bufferSize - 1] == 0); - return bufferSize-1; + return bufferSize - 1; } } } @@ -172,11 +173,12 @@ int InfixPrefix( // Add the closing system parenthesis numberOfChar += UTF8Decoder::CodePointToChars(needsSystemParentheses ? UCodePointRightSystemParenthesis : CodePoint(')'), buffer+numberOfChar, bufferSize - numberOfChar); if (numberOfChar >= bufferSize-1) { - return bufferSize-1; + assert(buffer[bufferSize - 1] == 0); + return bufferSize - 1; } } - buffer[numberOfChar] = 0; + assert(buffer[numberOfChar] == 0); return numberOfChar; } @@ -217,7 +219,7 @@ int SerializationHelper::CodePoint(char * buffer, int bufferSize, class CodePoin if (size <= bufferSize - 1) { buffer[size] = 0; } else { - assert(size -1 == bufferSize - 1); + assert(size - 1 == bufferSize - 1); buffer[--size] = 0; } return size; diff --git a/poincare/src/symbol.cpp b/poincare/src/symbol.cpp index 2364a05eb..a9d9f2229 100644 --- a/poincare/src/symbol.cpp +++ b/poincare/src/symbol.cpp @@ -16,6 +16,8 @@ namespace Poincare { +static inline int minInt(int x, int y) { return x < y ? x : y; } + constexpr char Symbol::k_ans[]; SymbolNode::SymbolNode(const char * newName, int length) : SymbolAbstractNode() { @@ -108,7 +110,7 @@ int SymbolNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloat if (bufferSize == 0) { return -1; } - return strlcpy(buffer, m_name, bufferSize); + return minInt(bufferSize - 1, strlcpy(buffer, m_name, bufferSize)); } Expression SymbolNode::shallowReduce(ReductionContext reductionContext) { diff --git a/poincare/src/undefined.cpp b/poincare/src/undefined.cpp index 7075a18b3..4e9a10b06 100644 --- a/poincare/src/undefined.cpp +++ b/poincare/src/undefined.cpp @@ -28,8 +28,7 @@ int UndefinedNode::serialize(char * buffer, int bufferSize, Preferences::PrintFl if (bufferSize == 0) { return -1; } - strlcpy(buffer, Undefined::Name(), bufferSize); - return minInt(Undefined::NameSize(), bufferSize) - 1; + return minInt(strlcpy(buffer, Undefined::Name(), bufferSize), bufferSize - 1); } template Evaluation UndefinedNode::templatedApproximate() const { diff --git a/poincare/src/unreal.cpp b/poincare/src/unreal.cpp index 9d6c1e0df..c46f3f1a4 100644 --- a/poincare/src/unreal.cpp +++ b/poincare/src/unreal.cpp @@ -18,8 +18,7 @@ int UnrealNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloat if (bufferSize == 0) { return -1; } - strlcpy(buffer, Unreal::Name(), bufferSize); - return minInt(Unreal::NameSize(), bufferSize) - 1; + return minInt(strlcpy(buffer, Unreal::Name(), bufferSize), bufferSize - 1); } } diff --git a/poincare/src/vertical_offset_layout.cpp b/poincare/src/vertical_offset_layout.cpp index ed5f46cc3..35aec2303 100644 --- a/poincare/src/vertical_offset_layout.cpp +++ b/poincare/src/vertical_offset_layout.cpp @@ -8,6 +8,8 @@ namespace Poincare { +static inline int minInt(int x, int y) { return x < y ? x : y; } + void VerticalOffsetLayoutNode::moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) { if (cursor->layoutNode() == indiceLayout() && cursor->position() == LayoutCursor::Position::Left) @@ -168,10 +170,9 @@ int VerticalOffsetLayoutNode::serialize(char * buffer, int bufferSize, Preferenc if (numberOfChar >= bufferSize-1) { return bufferSize-1; } numberOfChar += SerializationHelper::CodePoint(buffer+numberOfChar, bufferSize-numberOfChar, '}'); - if (numberOfChar >= bufferSize-1) { return bufferSize-1; } - - return numberOfChar; + return minInt(numberOfChar, bufferSize-1); } + assert(m_position == Position::Superscript); // If the layout is a superscript, write: '^' 'System(' indice 'System)' int numberOfChar = SerializationHelper::CodePoint(buffer, bufferSize, '^'); @@ -181,10 +182,7 @@ int VerticalOffsetLayoutNode::serialize(char * buffer, int bufferSize, Preferenc numberOfChar += const_cast(this)->indiceLayout()->serialize(buffer+numberOfChar, bufferSize-numberOfChar, floatDisplayMode, numberOfSignificantDigits); if (numberOfChar >= bufferSize-1) { return bufferSize-1; } numberOfChar += SerializationHelper::CodePoint(buffer+numberOfChar, bufferSize-numberOfChar, UCodePointRightSystemParenthesis); - if (numberOfChar >= bufferSize-1) { return bufferSize-1; } - - buffer[numberOfChar] = 0; - return numberOfChar; + return minInt(numberOfChar, bufferSize-1); } KDSize VerticalOffsetLayoutNode::computeSize() {