From a749a59e2a7c971f4fd160934e942cd7312b0a30 Mon Sep 17 00:00:00 2001
From: levBagryansky <28lev11@gmail.com>
Date: Mon, 8 Jul 2024 17:17:06 +0300
Subject: [PATCH 1/3] #3239: BytesOf refactoring
---
.../src/main/java/org/eolang/BytesOf.java | 173 ++----------
.../src/main/java/org/eolang/BytesRaw.java | 252 ++++++++++++++++++
2 files changed, 268 insertions(+), 157 deletions(-)
create mode 100644 eo-runtime/src/main/java/org/eolang/BytesRaw.java
diff --git a/eo-runtime/src/main/java/org/eolang/BytesOf.java b/eo-runtime/src/main/java/org/eolang/BytesOf.java
index af6260bd6d..d6187c6ec9 100644
--- a/eo-runtime/src/main/java/org/eolang/BytesOf.java
+++ b/eo-runtime/src/main/java/org/eolang/BytesOf.java
@@ -31,27 +31,22 @@
* Bytes.
*
* @since 1.0
- * @todo #3160:90min This class requires refactoring. As a result of refactoring you should remove
- * {@code @SuppressWarnings("PMD.GodClass")} from this class and
- * {@code @SuppressWarnings("PMD.CognitiveComplexity")} from {@link BytesOf#shift} method. You can
- * check description of this rules here
- * pmd.github.io
*/
@Versionized
-@SuppressWarnings({"PMD.TooManyMethods", "PMD.GodClass"})
+@SuppressWarnings("PMD.TooManyMethods")
public final class BytesOf implements Bytes {
/**
- * Binary data.
+ * Bytes.
*/
- private final byte[] data;
+ private final Bytes bytes;
/**
* Ctor.
* @param data Data.
*/
public BytesOf(final byte[] data) {
- this.data = Arrays.copyOf(data, data.length);
+ this.bytes = new BytesRaw(Arrays.copyOf(data, data.length));
}
/**
@@ -96,200 +91,64 @@ public BytesOf(final double number) {
@Override
public Bytes not() {
- final byte[] copy = this.take();
- for (int index = 0; index < copy.length; index += 1) {
- copy[index] = (byte) ~copy[index];
- }
- return new BytesOf(copy);
+ return this.bytes.not();
}
@Override
public Bytes and(final Bytes other) {
- final byte[] first = this.take();
- final byte[] second = other.take();
- for (int index = 0; index < Math.min(first.length, second.length); index += 1) {
- first[index] = (byte) (first[index] & second[index]);
- }
- return new BytesOf(first);
+ return this.bytes.and(other);
}
@Override
@SuppressWarnings("PMD.ShortMethodName")
public Bytes or(final Bytes other) {
- final byte[] first = this.take();
- final byte[] second = other.take();
- for (int index = 0; index < Math.min(first.length, second.length); index += 1) {
- first[index] = (byte) (first[index] | second[index]);
- }
- return new BytesOf(first);
+ return this.bytes.or(other);
}
@Override
public Bytes xor(final Bytes other) {
- final byte[] first = this.take();
- final byte[] second = other.take();
- for (int index = 0; index < Math.min(first.length, second.length); index += 1) {
- first[index] = (byte) (first[index] ^ second[index]);
- }
- return new BytesOf(first);
+ return this.bytes.xor(other);
}
@Override
@SuppressWarnings("PMD.CognitiveComplexity")
public Bytes shift(final int bits) {
- // @checkstyle MethodBodyCommentsCheck (3 lines)
- // @checkstyle NestedIfDepthCheck (40 lines)
- final byte[] bytes = this.take();
- final int mod = Math.abs(bits) % Byte.SIZE;
- final int offset = Math.abs(bits) / Byte.SIZE;
- if (bits < 0) {
- final byte carry = (byte) ((0x01 << mod) - 1);
- for (int index = 0; index < bytes.length; index += 1) {
- final int source = index + offset;
- if (source >= bytes.length) {
- bytes[index] = 0;
- } else {
- byte dst = (byte) (bytes[source] << mod);
- if (source + 1 < bytes.length) {
- dst |= bytes[source + 1] >>> (Byte.SIZE - mod) & (carry & 0xFF);
- }
- bytes[index] = dst;
- }
- }
- } else {
- final byte carry = (byte) (0xFF << (Byte.SIZE - mod));
- for (int index = bytes.length - 1; index >= 0; index -= 1) {
- final int source = index - offset;
- if (source < 0) {
- bytes[index] = 0;
- } else {
- byte dst = (byte) ((0xff & bytes[source]) >>> mod);
- if (source - 1 >= 0) {
- dst |= bytes[source - 1] << (Byte.SIZE - mod) & (carry & 0xFF);
- }
- bytes[index] = dst;
- }
- }
- }
- return new BytesOf(bytes);
+ return this.bytes.shift(bits);
}
@Override
public Bytes sshift(final int bits) {
- if (bits < 0) {
- throw new UnsupportedOperationException("right sshift is NYI");
- }
- final byte[] bytes = this.shift(bits).take();
- if (this.take()[0] < 0) {
- for (int index = 0; index < bytes.length; index += 1) {
- final int zeros = BytesOf.numberOfLeadingZeros(
- bytes[index]
- );
- bytes[index] = (byte) (bytes[index] & 0xFF ^ (-1 << (Byte.SIZE - zeros)));
- if (zeros != Byte.SIZE) {
- break;
- }
- }
- }
- return new BytesOf(bytes);
+ return this.bytes.sshift(bits);
}
@Override
public T asNumber(final Class type) {
- final byte[] ret = this.take();
- final Object res;
- final ByteBuffer buf = ByteBuffer.wrap(ret);
- if (Long.class.equals(type)
- && ret.length == Long.BYTES) {
- res = buf.getLong();
- } else if (Integer.class.equals(type)
- && ret.length == Integer.BYTES
- ) {
- res = buf.getInt();
- } else if (Double.class.equals(type)
- && ret.length == Double.BYTES
- ) {
- res = buf.getDouble();
- } else {
- throw new UnsupportedOperationException(
- String.format(
- "Unsupported conversion to '%s' for %d bytes",
- type,
- ret.length
- )
- );
- }
- return type.cast(res);
+ return this.bytes.asNumber(type);
}
@Override
public String asString() {
- final StringBuilder out = new StringBuilder(0);
- for (final byte bte : this.data) {
- if (out.length() > 0) {
- out.append('-');
- }
- out.append(String.format("%02X", bte));
- }
- if (this.data.length == 0) {
- out.append("--");
- }
- return out.toString();
+ return this.bytes.asString();
}
@Override
public byte[] take() {
- return Arrays.copyOf(this.data, this.data.length);
+ return this.bytes.take();
}
@Override
public String toString() {
- return String.format("BytesOf{%s}", Arrays.toString(this.data));
+ return this.bytes.toString();
}
@Override
public boolean equals(final Object other) {
- final boolean result;
- if (this == other) {
- result = true;
- } else if (other instanceof Bytes) {
- result = Arrays.equals(this.data, ((Bytes) other).take());
- } else {
- result = false;
- }
- return result;
+ return this.bytes.equals(other);
}
@Override
public int hashCode() {
- return Arrays.hashCode(this.data);
- }
-
- /**
- * Count leading zero bits.
- * @param num Byte.
- * @return Number between 0 and 8.
- */
- private static byte numberOfLeadingZeros(final byte num) {
- final byte result;
- if (num == 0) {
- result = (byte) Byte.SIZE;
- } else if (num < 0) {
- result = (byte) 0;
- } else {
- byte temp = num;
- int bts = Byte.SIZE - 1;
- if (temp >= 1 << 4) {
- bts -= 4;
- temp >>>= 4;
- }
- if (temp >= 1 << 2) {
- bts -= 2;
- temp >>>= 2;
- }
- result = (byte) (bts - (temp >>> 1));
- }
- return result;
+ return this.bytes.hashCode();
}
}
diff --git a/eo-runtime/src/main/java/org/eolang/BytesRaw.java b/eo-runtime/src/main/java/org/eolang/BytesRaw.java
new file mode 100644
index 0000000000..93331d3cee
--- /dev/null
+++ b/eo-runtime/src/main/java/org/eolang/BytesRaw.java
@@ -0,0 +1,252 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016-2024 Objectionary.com
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package org.eolang;
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+
+/**
+ * Bytes to be created from byte array only.
+ *
+ * @since 1.0
+ * @todo #3239:90min Method {@link BytesOf#shift} should be refactored to get rid of
+ * {@code @SuppressWarnings("PMD.CognitiveComplexity")} warning. You can
+ * check description of this rules here
+ * pmd.github.io
+ */
+@Versionized
+@SuppressWarnings("PMD.TooManyMethods")
+class BytesRaw implements Bytes {
+
+ /**
+ * Binary data.
+ */
+ private final byte[] data;
+
+ /**
+ * Ctor.
+ * @param data Data.
+ */
+ BytesRaw(final byte[] data) {
+ this.data = Arrays.copyOf(data, data.length);
+ }
+
+ @Override
+ public Bytes not() {
+ final byte[] copy = this.take();
+ for (int index = 0; index < copy.length; index += 1) {
+ copy[index] = (byte) ~copy[index];
+ }
+ return new BytesOf(copy);
+ }
+
+ @Override
+ public Bytes and(final Bytes other) {
+ final byte[] first = this.take();
+ final byte[] second = other.take();
+ for (int index = 0; index < Math.min(first.length, second.length); index += 1) {
+ first[index] = (byte) (first[index] & second[index]);
+ }
+ return new BytesOf(first);
+ }
+
+ @Override
+ @SuppressWarnings("PMD.ShortMethodName")
+ public Bytes or(final Bytes other) {
+ final byte[] first = this.take();
+ final byte[] second = other.take();
+ for (int index = 0; index < Math.min(first.length, second.length); index += 1) {
+ first[index] = (byte) (first[index] | second[index]);
+ }
+ return new BytesOf(first);
+ }
+
+ @Override
+ public Bytes xor(final Bytes other) {
+ final byte[] first = this.take();
+ final byte[] second = other.take();
+ for (int index = 0; index < Math.min(first.length, second.length); index += 1) {
+ first[index] = (byte) (first[index] ^ second[index]);
+ }
+ return new BytesOf(first);
+ }
+
+ @Override
+ @SuppressWarnings("PMD.CognitiveComplexity")
+ public Bytes shift(final int bits) {
+ // @checkstyle MethodBodyCommentsCheck (3 lines)
+ // @checkstyle NestedIfDepthCheck (40 lines)
+ final byte[] bytes = this.take();
+ final int mod = Math.abs(bits) % Byte.SIZE;
+ final int offset = Math.abs(bits) / Byte.SIZE;
+ if (bits < 0) {
+ final byte carry = (byte) ((0x01 << mod) - 1);
+ for (int index = 0; index < bytes.length; index += 1) {
+ final int source = index + offset;
+ if (source >= bytes.length) {
+ bytes[index] = 0;
+ } else {
+ byte dst = (byte) (bytes[source] << mod);
+ if (source + 1 < bytes.length) {
+ dst |= bytes[source + 1] >>> (Byte.SIZE - mod) & (carry & 0xFF);
+ }
+ bytes[index] = dst;
+ }
+ }
+ } else {
+ final byte carry = (byte) (0xFF << (Byte.SIZE - mod));
+ for (int index = bytes.length - 1; index >= 0; index -= 1) {
+ final int source = index - offset;
+ if (source < 0) {
+ bytes[index] = 0;
+ } else {
+ byte dst = (byte) ((0xff & bytes[source]) >>> mod);
+ if (source - 1 >= 0) {
+ dst |= bytes[source - 1] << (Byte.SIZE - mod) & (carry & 0xFF);
+ }
+ bytes[index] = dst;
+ }
+ }
+ }
+ return new BytesOf(bytes);
+ }
+
+ @Override
+ public Bytes sshift(final int bits) {
+ if (bits < 0) {
+ throw new UnsupportedOperationException("right sshift is NYI");
+ }
+ final byte[] bytes = this.shift(bits).take();
+ if (this.take()[0] < 0) {
+ for (int index = 0; index < bytes.length; index += 1) {
+ final int zeros = BytesRaw.numberOfLeadingZeros(
+ bytes[index]
+ );
+ bytes[index] = (byte) (bytes[index] & 0xFF ^ (-1 << (Byte.SIZE - zeros)));
+ if (zeros != Byte.SIZE) {
+ break;
+ }
+ }
+ }
+ return new BytesOf(bytes);
+ }
+
+ @Override
+ public T asNumber(final Class type) {
+ final byte[] ret = this.take();
+ final Object res;
+ final ByteBuffer buf = ByteBuffer.wrap(ret);
+ if (Long.class.equals(type)
+ && ret.length == Long.BYTES) {
+ res = buf.getLong();
+ } else if (Integer.class.equals(type)
+ && ret.length == Integer.BYTES
+ ) {
+ res = buf.getInt();
+ } else if (Double.class.equals(type)
+ && ret.length == Double.BYTES
+ ) {
+ res = buf.getDouble();
+ } else {
+ throw new UnsupportedOperationException(
+ String.format(
+ "Unsupported conversion to '%s' for %d bytes",
+ type,
+ ret.length
+ )
+ );
+ }
+ return type.cast(res);
+ }
+
+ @Override
+ public String asString() {
+ final StringBuilder out = new StringBuilder(0);
+ for (final byte bte : this.data) {
+ if (out.length() > 0) {
+ out.append('-');
+ }
+ out.append(String.format("%02X", bte));
+ }
+ if (this.data.length == 0) {
+ out.append("--");
+ }
+ return out.toString();
+ }
+
+ @Override
+ public byte[] take() {
+ return Arrays.copyOf(this.data, this.data.length);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("BytesOf{%s}", Arrays.toString(this.data));
+ }
+
+ @Override
+ public boolean equals(final Object other) {
+ final boolean result;
+ if (this == other) {
+ result = true;
+ } else if (other instanceof Bytes) {
+ result = Arrays.equals(this.data, ((Bytes) other).take());
+ } else {
+ result = false;
+ }
+ return result;
+ }
+
+ @Override
+ public int hashCode() {
+ return Arrays.hashCode(this.data);
+ }
+
+ /**
+ * Count leading zero bits.
+ * @param num Byte.
+ * @return Number between 0 and 8.
+ */
+ private static byte numberOfLeadingZeros(final byte num) {
+ final byte result;
+ if (num == 0) {
+ result = (byte) Byte.SIZE;
+ } else if (num < 0) {
+ result = (byte) 0;
+ } else {
+ byte temp = num;
+ int bts = Byte.SIZE - 1;
+ if (temp >= 1 << 4) {
+ bts -= 4;
+ temp >>>= 4;
+ }
+ if (temp >= 1 << 2) {
+ bts -= 2;
+ temp >>>= 2;
+ }
+ result = (byte) (bts - (temp >>> 1));
+ }
+ return result;
+ }
+}
From 26d8412d04f5146e2c325a5eaf8f77fcb7da7c7d Mon Sep 17 00:00:00 2001
From: levBagryansky <28lev11@gmail.com>
Date: Tue, 9 Jul 2024 14:15:01 +0300
Subject: [PATCH 2/3] #3239: Added one more ctor
---
eo-runtime/src/main/java/org/eolang/BytesOf.java | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/eo-runtime/src/main/java/org/eolang/BytesOf.java b/eo-runtime/src/main/java/org/eolang/BytesOf.java
index d6187c6ec9..a1d895387c 100644
--- a/eo-runtime/src/main/java/org/eolang/BytesOf.java
+++ b/eo-runtime/src/main/java/org/eolang/BytesOf.java
@@ -41,12 +41,19 @@ public final class BytesOf implements Bytes {
*/
private final Bytes bytes;
+ /**
+ * Ctor.
+ * @param bytes Bytes.
+ */
+ public BytesOf(final Bytes bytes) {
+ this.bytes = bytes;
+ }
/**
* Ctor.
* @param data Data.
*/
public BytesOf(final byte[] data) {
- this.bytes = new BytesRaw(Arrays.copyOf(data, data.length));
+ this(new BytesRaw(Arrays.copyOf(data, data.length)));
}
/**
From 255fe2238898ee052ccc3aca194779ebd00687d0 Mon Sep 17 00:00:00 2001
From: levBagryansky <28lev11@gmail.com>
Date: Tue, 9 Jul 2024 14:17:44 +0300
Subject: [PATCH 3/3] #3239: pqulice violation
---
eo-runtime/src/main/java/org/eolang/BytesOf.java | 1 +
1 file changed, 1 insertion(+)
diff --git a/eo-runtime/src/main/java/org/eolang/BytesOf.java b/eo-runtime/src/main/java/org/eolang/BytesOf.java
index a1d895387c..502a1b4909 100644
--- a/eo-runtime/src/main/java/org/eolang/BytesOf.java
+++ b/eo-runtime/src/main/java/org/eolang/BytesOf.java
@@ -48,6 +48,7 @@ public final class BytesOf implements Bytes {
public BytesOf(final Bytes bytes) {
this.bytes = bytes;
}
+
/**
* Ctor.
* @param data Data.