001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.juneau.commons.lang; 018 019import static org.apache.juneau.commons.utils.Shorts.*; 020 021import org.apache.juneau.commons.utils.*; 022 023/** 024 * A simple mutable byte value. 025 * 026 * <p> 027 * This class extends {@link Holder}<{@link Byte}> and adds convenience methods for incrementing, 028 * decrementing, and testing byte values, which are useful in lambdas and byte manipulation operations. 029 * 030 * <h5 class='section'>Notes:</h5><ul> 031 * <li class='note'> 032 * This class is <b>not thread-safe</b>. For concurrent access, use synchronization or atomic classes. 033 * </ul> 034 * 035 * <h5 class='section'>Example:</h5> 036 * <p class='bjava'> 037 * <jc>// Create a counter</jc> 038 * ByteHolder <jv>counter</jv> = ByteHolder.<jsm>create</jsm>(); 039 * 040 * <jc>// Use in a lambda to count items</jc> 041 * list.forEach(<jv>x</jv> -> { 042 * <jk>if</jk> (<jv>x</jv>.isValid()) { 043 * <jv>counter</jv>.increment(); 044 * } 045 * }); 046 * 047 * <jsm>log</jsm>(<js>"Count: "</js> + <jv>counter</jv>.get()); 048 * </p> 049 * 050 * <h5 class='section'>See Also:</h5><ul> 051 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauCommonsLang">Lang Package</a> 052 * </ul> 053 */ 054@SuppressWarnings({ 055 "java:S1192" // Duplicated literals (argument/property names) read more clearly inline than as constants 056}) 057public class ByteHolder extends Holder<Byte> { 058 059 /** 060 * Creates a new byte value initialized to <c>0</c>. 061 * 062 * <h5 class='section'>Example:</h5> 063 * <p class='bjava'> 064 * ByteHolder <jv>counter</jv> = ByteHolder.<jsm>create</jsm>(); 065 * <jsm>assertEquals</jsm>(0, <jv>counter</jv>.get()); 066 * </p> 067 * 068 * @return A new byte value. 069 */ 070 public static ByteHolder create() { 071 return of((byte)0); 072 } 073 074 /** 075 * Creates a new byte value with the specified initial value. 076 * 077 * <h5 class='section'>Example:</h5> 078 * <p class='bjava'> 079 * ByteHolder <jv>value</jv> = ByteHolder.<jsm>of</jsm>((<jk>byte</jk>)42); 080 * <jsm>assertEquals</jsm>(42, <jv>value</jv>.get()); 081 * </p> 082 * 083 * @param value The initial value. Can be <jk>null</jk> (treated as <c>0</c>). 084 * @return A new byte value. 085 */ 086 public static ByteHolder of(Byte value) { 087 return new ByteHolder(value); 088 } 089 090 /** 091 * Constructor. 092 */ 093 public ByteHolder() { 094 super((byte)0); 095 } 096 097 /** 098 * Constructor. 099 * 100 * @param value The initial value. Can be <jk>null</jk> (treated as <c>0</c>). 101 */ 102 public ByteHolder(Byte value) { 103 super(value == null ? 0 : value); 104 } 105 106 /** 107 * Adds the specified value to the current value. 108 * 109 * <h5 class='section'>Example:</h5> 110 * <p class='bjava'> 111 * ByteHolder <jv>value</jv> = ByteHolder.<jsm>of</jsm>((<jk>byte</jk>)10); 112 * <jv>value</jv>.add((<jk>byte</jk>)5); 113 * <jsm>assertEquals</jsm>(15, <jv>value</jv>.get()); 114 * </p> 115 * 116 * @param x The value to add. Can be <jk>null</jk> (treated as <c>0</c>). 117 * @return This object. 118 */ 119 public ByteHolder add(Byte x) { 120 var v = get(); 121 set((byte)((v == null ? 0 : v) + (x == null ? 0 : x))); 122 return this; 123 } 124 125 /** 126 * Adds the specified value to the current value and returns the new value. 127 * 128 * <h5 class='section'>Example:</h5> 129 * <p class='bjava'> 130 * ByteHolder <jv>value</jv> = ByteHolder.<jsm>of</jsm>((<jk>byte</jk>)10); 131 * <jk>byte</jk> <jv>result</jv> = <jv>value</jv>.addAndGet((<jk>byte</jk>)5); <jc>// Returns 15</jc> 132 * <jsm>assertEquals</jsm>(15, <jv>value</jv>.get()); 133 * </p> 134 * 135 * @param x The value to add. Can be <jk>null</jk> (treated as <c>0</c>). 136 * @return The new value after addition. 137 */ 138 public Byte addAndGet(Byte x) { 139 var v = get(); 140 var result = (byte)((v == null ? 0 : v) + (x == null ? 0 : x)); 141 set(result); 142 return result; 143 } 144 145 /** 146 * Decrements the value by 1. 147 * 148 * <h5 class='section'>Example:</h5> 149 * <p class='bjava'> 150 * ByteHolder <jv>counter</jv> = ByteHolder.<jsm>of</jsm>((<jk>byte</jk>)5); 151 * <jv>counter</jv>.decrement(); 152 * <jsm>assertEquals</jsm>(4, <jv>counter</jv>.get()); 153 * </p> 154 * 155 * @return This object. 156 */ 157 public ByteHolder decrement() { 158 var v = get(); 159 set((byte)((v == null ? 0 : v) - 1)); 160 return this; 161 } 162 163 /** 164 * Decrements the value by 1 and returns the new value. 165 * 166 * <h5 class='section'>Example:</h5> 167 * <p class='bjava'> 168 * ByteHolder <jv>counter</jv> = ByteHolder.<jsm>of</jsm>((<jk>byte</jk>)5); 169 * <jk>byte</jk> <jv>result</jv> = <jv>counter</jv>.decrementAndGet(); <jc>// Returns 4</jc> 170 * <jsm>assertEquals</jsm>(4, <jv>counter</jv>.get()); 171 * </p> 172 * 173 * @return The decremented value. 174 */ 175 public Byte decrementAndGet() { 176 var v = get(); 177 var result = (byte)((v == null ? 0 : v) - 1); 178 set(result); 179 return result; 180 } 181 182 /** 183 * Increments the value by 1. 184 * 185 * <h5 class='section'>Example:</h5> 186 * <p class='bjava'> 187 * ByteHolder <jv>counter</jv> = ByteHolder.<jsm>of</jsm>((<jk>byte</jk>)5); 188 * <jv>counter</jv>.increment(); 189 * <jsm>assertEquals</jsm>(6, <jv>counter</jv>.get()); 190 * </p> 191 * 192 * @return This object. 193 */ 194 public ByteHolder increment() { 195 var v = get(); 196 set((byte)((v == null ? 0 : v) + 1)); 197 return this; 198 } 199 200 /** 201 * Increments the value by 1 and returns the new value. 202 * 203 * <h5 class='section'>Example:</h5> 204 * <p class='bjava'> 205 * ByteHolder <jv>counter</jv> = ByteHolder.<jsm>of</jsm>((<jk>byte</jk>)5); 206 * <jk>byte</jk> <jv>result</jv> = <jv>counter</jv>.incrementAndGet(); <jc>// Returns 6</jc> 207 * <jsm>assertEquals</jsm>(6, <jv>counter</jv>.get()); 208 * </p> 209 * 210 * @return The incremented value. 211 */ 212 public Byte incrementAndGet() { 213 var v = get(); 214 var result = (byte)((v == null ? 0 : v) + 1); 215 set(result); 216 return result; 217 } 218 219 /** 220 * Checks if the current value is equal to the specified value. 221 * 222 * <p> 223 * Uses {@link Shorts#eq(Object, Object)} for deep equality comparison, which handles nulls safely. 224 * 225 * <h5 class='section'>Example:</h5> 226 * <p class='bjava'> 227 * ByteHolder <jv>value</jv> = ByteHolder.<jsm>of</jsm>((<jk>byte</jk>)42); 228 * <jsm>assertTrue</jsm>(<jv>value</jv>.is((<jk>byte</jk>)42)); 229 * <jsm>assertFalse</jsm>(<jv>value</jv>.is((<jk>byte</jk>)43)); 230 * </p> 231 * 232 * @param value The value to compare to. Can be <jk>null</jk>. 233 * @return <jk>true</jk> if the current value is equal to the specified value. 234 */ 235 @Override 236 public boolean is(Byte value) { 237 return eq(get(), value); 238 } 239 240 /** 241 * Checks if the current value matches any of the specified values. 242 * 243 * <p> 244 * Uses {@link Shorts#eq(Object, Object)} for deep equality comparison of each value. 245 * 246 * <h5 class='section'>Example:</h5> 247 * <p class='bjava'> 248 * ByteHolder <jv>value</jv> = ByteHolder.<jsm>of</jsm>((<jk>byte</jk>)5); 249 * <jsm>assertTrue</jsm>(<jv>value</jv>.isAny((<jk>byte</jk>)3, (<jk>byte</jk>)5, (<jk>byte</jk>)7)); 250 * <jsm>assertFalse</jsm>(<jv>value</jv>.isAny((<jk>byte</jk>)1, (<jk>byte</jk>)2)); 251 * </p> 252 * 253 * @param values The values to compare to. Must not be <jk>null</jk>. 254 * @return <jk>true</jk> if the current value matches any of the specified values. 255 */ 256 public boolean isAny(Byte...values) { 257 reqnn("values", values); 258 var current = get(); 259 for (var value : values) 260 if (eq(current, value)) 261 return true; 262 return false; 263 } 264}