001// Copyright (c) FIRST and other WPILib contributors. 002// Open Source Software; you can modify and/or share it under the terms of 003// the WPILib BSD license file in the root directory of this project. 004 005package edu.wpi.first.util.struct; 006 007import java.util.Map; 008 009/** Raw struct dynamic field descriptor. */ 010public class StructFieldDescriptor { 011 private static int toBitWidth(int size, int bitWidth) { 012 if (bitWidth == 0) { 013 return size * 8; 014 } else { 015 return bitWidth; 016 } 017 } 018 019 private static long toBitMask(int size, int bitWidth) { 020 if (size == 0) { 021 return 0; 022 } else { 023 return -1L >>> (64 - toBitWidth(size, bitWidth)); 024 } 025 } 026 027 // does not fill in offset, shift 028 StructFieldDescriptor( 029 StructDescriptor parent, 030 String name, 031 StructFieldType type, 032 int size, 033 int arraySize, 034 int bitWidth, 035 Map<String, Long> enumValues, 036 StructDescriptor structDesc) { 037 m_parent = parent; 038 m_name = name; 039 m_size = size; 040 m_arraySize = arraySize; 041 m_enum = enumValues; 042 m_struct = structDesc; 043 m_bitMask = toBitMask(size, bitWidth); 044 m_type = type; 045 m_bitWidth = toBitWidth(size, bitWidth); 046 } 047 048 /** 049 * Gets the dynamic struct this field is contained in. 050 * 051 * @return struct descriptor 052 */ 053 public StructDescriptor getParent() { 054 return m_parent; 055 } 056 057 /** 058 * Gets the field name. 059 * 060 * @return field name 061 */ 062 public String getName() { 063 return m_name; 064 } 065 066 /** 067 * Gets the field type. 068 * 069 * @return field type 070 */ 071 public StructFieldType getType() { 072 return m_type; 073 } 074 075 /** 076 * Returns whether the field type is a signed integer. 077 * 078 * @return true if signed integer, false otherwise 079 */ 080 public boolean isInt() { 081 return m_type.isInt; 082 } 083 084 /** 085 * Returns whether the field type is an unsigned integer. 086 * 087 * @return true if unsigned integer, false otherwise 088 */ 089 public boolean isUint() { 090 return m_type.isUint; 091 } 092 093 /** 094 * Gets the underlying storage size of the field, in bytes. 095 * 096 * @return number of bytes 097 */ 098 public int getSize() { 099 return m_size; 100 } 101 102 /** 103 * Gets the storage offset of the field, in bytes. 104 * 105 * @return number of bytes from the start of the struct 106 */ 107 public int getOffset() { 108 return m_offset; 109 } 110 111 /** 112 * Gets the bit width of the field, in bits. 113 * 114 * @return number of bits 115 */ 116 public int getBitWidth() { 117 return m_bitWidth == 0 ? m_size * 8 : m_bitWidth; 118 } 119 120 /** 121 * Gets the bit mask for the field. The mask is always the least significant bits (it is not 122 * shifted). 123 * 124 * @return bit mask 125 */ 126 public long getBitMask() { 127 return m_bitMask; 128 } 129 130 /** 131 * Gets the bit shift for the field (LSB=0). 132 * 133 * @return number of bits 134 */ 135 public int getBitShift() { 136 return m_bitShift; 137 } 138 139 /** 140 * Returns whether the field is an array. 141 * 142 * @return true if array 143 */ 144 public boolean isArray() { 145 return m_arraySize > 1; 146 } 147 148 /** 149 * Gets the array size. Returns 1 if non-array. 150 * 151 * @return number of elements 152 */ 153 public int getArraySize() { 154 return m_arraySize; 155 } 156 157 /** 158 * Returns whether the field has enumerated values. 159 * 160 * @return true if there are enumerated values 161 */ 162 public boolean hasEnum() { 163 return m_enum != null; 164 } 165 166 /** 167 * Gets the enumerated values. 168 * 169 * @return set of enumerated values 170 */ 171 public Map<String, Long> getEnumValues() { 172 return m_enum; 173 } 174 175 /** 176 * Gets the struct descriptor for a struct data type. 177 * 178 * @return struct descriptor; returns null for non-struct 179 */ 180 public StructDescriptor getStruct() { 181 return m_struct; 182 } 183 184 /** 185 * Gets the minimum unsigned integer value that can be stored in this field. 186 * 187 * @return minimum value 188 */ 189 public long getUintMin() { 190 return 0; 191 } 192 193 /** 194 * Gets the maximum unsigned integer value that can be stored in this field. Note this is not the 195 * actual maximum for uint64 (due to Java lacking support for 64-bit unsigned integers). 196 * 197 * @return maximum value 198 */ 199 public long getUintMax() { 200 return m_bitMask; 201 } 202 203 /** 204 * Gets the minimum signed integer value that can be stored in this field. 205 * 206 * @return minimum value 207 */ 208 public long getIntMin() { 209 return -(m_bitMask >> 1) - 1; 210 } 211 212 /** 213 * Gets the maximum signed integer value that can be stored in this field. 214 * 215 * @return maximum value 216 */ 217 public long getIntMax() { 218 return m_bitMask >> 1; 219 } 220 221 /** 222 * Returns whether the field is a bitfield. 223 * 224 * @return true if bitfield 225 */ 226 public boolean isBitField() { 227 return m_bitShift != 0 || m_bitWidth != (m_size * 8); 228 } 229 230 private final StructDescriptor m_parent; 231 private final String m_name; 232 int m_size; 233 int m_offset; 234 final int m_arraySize; // 1 for non-arrays 235 private final Map<String, Long> m_enum; 236 private final StructDescriptor m_struct; // null for non-structs 237 private final long m_bitMask; 238 private final StructFieldType m_type; 239 private final int m_bitWidth; 240 int m_bitShift; 241}