Browse Source

compatibility fix for raspberry pi in FPC

Ugochukwu Mmaduekwe 7 years ago
parent
commit
34d0b6c2ce

+ 1 - 1
QRCodeGenLib.Demo/src/uQrCodeGeneratorDemo.pas

@@ -141,7 +141,7 @@ begin
   LGolden2 := '......';
   LQrCode := TQrCode.EncodeText(LGolden0 + LGolden1 + LGolden2,
     TQrCode.TEcc.eccLow, LEncoding);
-  WriteQrCodeToFile(LQrCode, 8, 5, 'phi-monolithic-QR.png');
+  WriteQrCodeToFile(LQrCode, 8, 5, 'phi-monolithic-QR');
 
   LSegs := TQRCodeGenLibGenericArray<IQrSegment>.Create
     (TQrSegment.MakeBytes(TConverters.ConvertStringToBytes(LGolden0, LEncoding)

+ 1 - 1
QRCodeGenLib.Demo/src/uQrCodeGeneratorDemoFMX.pas

@@ -134,7 +134,7 @@ begin
   LGolden2 := '......';
   LQrCode := TQrCode.EncodeText(LGolden0 + LGolden1 + LGolden2,
     TQrCode.TEcc.eccLow, LEncoding);
-  WriteQrCodeToFile(LQrCode, 8, 5, 'phi-monolithic-QR.png');
+  WriteQrCodeToFile(LQrCode, 8, 5, 'phi-monolithic-QR');
 
   LSegs := TQRCodeGenLibGenericArray<IQrSegment>.Create
     (TQrSegment.MakeBytes(TConverters.ConvertStringToBytes(LGolden0, LEncoding)

+ 1 - 1
QRCodeGenLib/src/Packages/FPC/QRCodeGenLib4PascalPackage.lpk

@@ -22,7 +22,7 @@
     <Description Value="QRCodeGenLib4Pascal is a Delphi/FPC compatible library that provides an easy to use interface for generating QR Codes.
 "/>
     <License Value="MIT License"/>
-    <Version Major="1" Minor="3"/>
+    <Version Major="1" Minor="4"/>
     <Files Count="18">
       <Item1>
         <Filename Value="..\..\QRCodeGen\QlpBitBuffer.pas"/>

+ 8 - 5
QRCodeGenLib/src/QRCodeGen/QlpBitBuffer.pas

@@ -107,7 +107,7 @@ end;
 
 class function TBitBuffer.Create(): TBitBuffer;
 begin
-  Result := Default(TBitBuffer);
+  Result := Default (TBitBuffer);
   System.SetLength(Result.FData, 64);
   Result.FBitLength := 0;
   Result.FBitBufferInitialized := True;
@@ -150,11 +150,12 @@ begin
     System.Assert((FBitLength and $1F) = 0);
 {$ENDIF DEBUG}
     ALength := ALength - LRemain;
-    AValue := AValue and ((1 shl ALength) - 1);
+    AValue := AValue and ((TBits.LeftShift32(1, ALength)) - 1);
     LRemain := 32;
   end;
   FData[TBits.Asr32(FBitLength, 5)] := FData[TBits.Asr32(FBitLength, 5)] or
-    (AValue shl (LRemain - ALength));
+    (TBits.LeftShift32(AValue, LRemain - ALength));
+
   FBitLength := FBitLength + ALength;
 end;
 
@@ -174,7 +175,8 @@ begin
   end;
   LWholeWords := ALength shr 5;
   LTailBits := ALength and 31;
-  if ((LTailBits > 0) and ((AValues[LWholeWords] shl LTailBits) <> 0)) then
+  if ((LTailBits > 0) and (TBits.LeftShift32(AValues[LWholeWords], LTailBits)
+    <> 0)) then
   begin
     raise EArgumentInvalidQRCodeGenLibException.CreateRes(@SLastWordError);
   end;
@@ -205,7 +207,8 @@ begin
       FData[TBits.Asr32(FBitLength, 5)] := FData[TBits.Asr32(FBitLength, 5)] or
         (LWord shr LShift);
       FBitLength := FBitLength + 32;
-      FData[TBits.Asr32(FBitLength, 5)] := LWord shl (32 - LShift);
+      FData[TBits.Asr32(FBitLength, 5)] :=
+        TBits.LeftShift32(LWord, (32 - LShift));
     end;
     if (LTailBits > 0) then
     begin

+ 4 - 3
QRCodeGenLib/src/QRCodeGen/QlpQrCode.pas

@@ -1015,12 +1015,12 @@ begin
   if (ABlack = 0) then
   begin
     FModules[TBits.Asr32(LIdx, 5)] := FModules[TBits.Asr32(LIdx, 5)] and
-      (not(1 shl LIdx));
+      (not(TBits.LeftShift32(1, LIdx)));
   end
   else if (ABlack = 1) then
   begin
     FModules[TBits.Asr32(LIdx, 5)] := FModules[TBits.Asr32(LIdx, 5)] or
-      (1 shl LIdx);
+      (TBits.LeftShift32(1, LIdx));
   end
   else
   begin
@@ -1349,7 +1349,8 @@ begin
     LBit := TQrCodeCommons.GetBit(AAllCodewords[TBits.Asr32(LIIdx, 3)],
       (not LIIdx) and 7);
     FModules[TBits.Asr32(LJIdx, 5)] := FModules[TBits.Asr32(LJIdx, 5)] or
-      (LBit shl LJIdx);
+      (TBits.LeftShift32(LBit, LJIdx));
+
   end;
 end;
 

+ 3 - 2
QRCodeGenLib/src/QRCodeGen/QlpQrSegment.pas

@@ -302,7 +302,7 @@ begin
   begin
     TGuard.RequireNotNull(LSegment, SSegmentInstanceNil);
     LCCBits := LSegment.Mode.NumCharCountBits(AVersion);
-    if (LSegment.NumChars >= (1 shl LCCBits)) then
+    if (LSegment.NumChars >= (TBits.LeftShift32(1, LCCBits))) then
     begin
       result := -1; // The segment's length doesn't fit the field's bit width
       Exit;
@@ -423,10 +423,11 @@ begin
   for LIdx := System.Low(AData) to System.High(AData) do
   begin
     LBits[TBits.Asr32(LIdx, 2)] := Int32(LBits[TBits.Asr32(LIdx, 2)] or
-          Int64((AData[LIdx] and $FF) shl ((not LIdx) shl 3)));
+      TBits.NegativeLeftShift32(AData[LIdx] and $FF, (not LIdx) shl 3));
   end;
   result := TQrSegment.Create(TQrSegmentMode.qsmByte, System.Length(AData),
     LBits, System.Length(AData) * 8);
+
 end;
 
 class function TQrSegment.MakeEci(const AAssignValue: Int32): IQrSegment;

+ 5 - 3
QRCodeGenLib/src/QRCodeGen/QlpQrTemplate.pas

@@ -107,6 +107,7 @@ begin
 
   DrawFunctionPatterns(); // Reads and writes fields
   FMasks := GenerateMasks(); // Reads fields, returns array
+
   FDataOutputBitIndexes := GenerateZigZagScan(); // Reads fields, returns array
   FIsFunction := Nil;
 end;
@@ -169,9 +170,9 @@ begin
 {$ENDIF DEBUG}
   LIdx := (Ay * FSize) + Ax;
   FTemplate[TBits.Asr32(LIdx, 5)] := FTemplate[TBits.Asr32(LIdx, 5)] or
-    (AEnable shl LIdx);
+    (TBits.LeftShift32(AEnable, LIdx));
   FIsFunction[TBits.Asr32(LIdx, 5)] := FIsFunction[TBits.Asr32(LIdx, 5)] or
-    (1 shl LIdx);
+    (TBits.LeftShift32(1, LIdx));
 end;
 
 class destructor TQrTemplate.DestroyQrTemplate;
@@ -399,7 +400,8 @@ begin
         end;
 
         LMaskModules[TBits.Asr32(LIdx, 5)] := LMaskModules[TBits.Asr32(LIdx, 5)
-          ] or (LBit shl LIdx);
+          ] or (TBits.LeftShift32(LBit, LIdx));
+
         System.Inc(Lx);
         System.Inc(LIdx);
       end;

+ 6 - 2
QRCodeGenLib/src/Utils/QlpArrayUtils.pas

@@ -77,9 +77,13 @@ end;
 
 class procedure TArrayUtils.Fill(const ABuffer: TQRCodeGenLibInt32Array;
   AFiller: Int32);
+var
+  LIdx: Int32;
 begin
-  System.FillChar(ABuffer[0], System.Length(ABuffer) *
-    System.SizeOf(Int32), AFiller);
+  for LIdx := System.Low(ABuffer) to System.High(ABuffer) do
+  begin
+    ABuffer[LIdx] := AFiller;
+  end;
 end;
 
 class procedure TArrayUtils.Fill(const ABuffer: TQRCodeGenLibByteArray;

+ 43 - 19
QRCodeGenLib/src/Utils/QlpBits.pas

@@ -23,16 +23,39 @@ type
       static; inline;
 
     /// <summary>
-    /// Calculates Arithmetic shift right.
+    /// Calculates Left Shift. This was implemented to circumvent an *issue*
+    /// in FPC ARM when performing Shift Left with <b>AShiftBits &gt; 32 .</b><br />
     /// </summary>
-    /// <param name="AValue">Int64 value to compute 'Asr' on.</param>
-    /// <param name="AShiftBits">Byte, number of bits to shift value to.</param>
-    /// <returns>Shifted value.</returns>
-    /// <remarks>
-    /// Emulated Implementation was gotten from FreePascal sources
-    /// </remarks>
+    /// <param name="AValue">
+    /// Int32 value to compute 'LS' on.
+    /// </param>
+    /// <param name="AShiftBits">
+    /// Int32, number of bits to shift value to.
+    /// </param>
+    /// <returns>
+    /// Shifted value.
+    /// </returns>
 
-    class function Asr64(AValue: Int64; AShiftBits: Byte): Int64;
+    class function LeftShift32(AValue: Int32; AShiftBits: Int32): Int32;
+      static; inline;
+
+    /// <summary>
+    /// Calculates Negative Left Shift. This was implemented to circumvent an
+    /// *issue* in FPC ARM when performing Shift Left on certain values with a
+    /// Negative Shift Bits. In some C Compilers, such operations are
+    /// "Undefined"
+    /// </summary>
+    /// <param name="AValue">
+    /// Int32 value to compute 'NLS' on.
+    /// </param>
+    /// <param name="AShiftBits">
+    /// Int32, number of bits to shift value to. This Number Must be Negative
+    /// </param>
+    /// <returns>
+    /// Shifted value.
+    /// </returns>
+
+    class function NegativeLeftShift32(AValue: Int32; AShiftBits: Int32): Int32;
       static; inline;
 
   end;
@@ -44,26 +67,27 @@ implementation
 class function TBits.Asr32(AValue: Int32; AShiftBits: Byte): Int32;
 
 begin
-{$IFDEF FPC}
+{$IF DEFINED(FPC) AND (NOT DEFINED(CPUARM))}
   Result := SarLongInt(AValue, AShiftBits);
 {$ELSE}
   Result := Int32(UInt32(UInt32(UInt32(AValue) shr (AShiftBits and 31)) or
     (UInt32(Int32(UInt32(0 - UInt32(UInt32(AValue) shr 31)) and
     UInt32(Int32(0 - (Ord((AShiftBits and 31) <> 0) { and 1 } )))))
     shl (32 - (AShiftBits and 31)))));
-{$ENDIF FPC}
+{$IFEND}
 end;
 
-class function TBits.Asr64(AValue: Int64; AShiftBits: Byte): Int64;
+class function TBits.LeftShift32(AValue, AShiftBits: Int32): Int32;
 begin
-{$IFDEF FPC}
-  Result := SarInt64(AValue, AShiftBits);
-{$ELSE}
-  Result := Int64(UInt64(UInt64(UInt64(AValue) shr (AShiftBits and 63)) or
-    (UInt64(Int64(UInt64(0 - UInt64(UInt64(AValue) shr 63)) and
-    UInt64(Int64(0 - (Ord((AShiftBits and 63) <> 0) { and 1 } )))))
-    shl (64 - (AShiftBits and 63)))));
-{$ENDIF FPC}
+  Result := AValue shl (AShiftBits and 31);
+end;
+
+class function TBits.NegativeLeftShift32(AValue, AShiftBits: Int32): Int32;
+begin
+{$IFDEF DEBUG}
+  System.Assert(AShiftBits < 0);
+{$ENDIF DEBUG}
+  Result := AValue shl ((32 + AShiftBits) and 31);
 end;
 
 end.