Extensibility support (serialization part)
[openflowjava.git] / openflow-protocol-impl / src / main / java / org / opendaylight / openflowjava / protocol / impl / util / ByteBufUtils.java
1 /*
2  * Copyright (c) 2013 Pantheon Technologies s.r.o. and others. All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9
10 package org.opendaylight.openflowjava.protocol.impl.util;
11
12 import io.netty.buffer.ByteBuf;
13 import io.netty.buffer.UnpooledByteBufAllocator;
14
15 import java.util.ArrayList;
16 import java.util.List;
17 import java.util.Map;
18 import java.util.Map.Entry;
19
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
22
23 import com.google.common.base.Joiner;
24
25 /** Class for common operations on ByteBuf
26  * @author michal.polkorab
27  * @author timotej.kubas
28  */
29 public abstract class ByteBufUtils {
30
31     /**
32      * Converts ByteBuf into String
33      * @param bb input ByteBuf
34      * @return String
35      */
36     public static String byteBufToHexString(ByteBuf bb) {
37         StringBuffer sb = new StringBuffer();
38         for (int i = bb.readerIndex(); i < (bb.readerIndex() + bb.readableBytes()); i++) {
39             sb.append(String.format(" %02x", bb.getUnsignedByte(i)));
40         }
41         return sb.toString().trim();
42     }
43     
44     /**
45      * Converts String into byte[]
46      * @param hexSrc input String
47      * @return byte[] filled with input data
48      */
49     public static byte[] hexStringToBytes(String hexSrc) {
50         return hexStringToBytes(hexSrc, true);
51     }
52     
53     /**
54      * Converts String into byte[]
55      * @param hexSrc input String
56      * @param withSpaces if there are spaces in string 
57      * @return byte[] filled with input data
58      */
59     public static byte[] hexStringToBytes(String hexSrc, boolean withSpaces ) {
60         String splitPattern = "\\s+";
61         if (!withSpaces) {
62             splitPattern = "(?<=\\G.{2})";
63         }
64         
65         String[] byteChips = hexSrc.split(splitPattern);
66         byte[] result = new byte[byteChips.length];
67         for (int i = 0; i < byteChips.length; i++) {
68             result[i] = (byte) Short.parseShort(byteChips[i], 16);
69         }
70         return result;
71     }
72     
73     /**
74      * Creates ByteBuf filled with specified data
75      * @param hexSrc input String of bytes in hex format
76      * @return ByteBuf with specified hexString converted
77      */
78     public static ByteBuf hexStringToByteBuf(String hexSrc) {
79         ByteBuf out = UnpooledByteBufAllocator.DEFAULT.buffer();
80         hexStringToByteBuf(hexSrc, out);
81         return out;
82     }
83     
84     /**
85      * Creates ByteBuf filled with specified data
86      * @param hexSrc input String of bytes in hex format
87      * @param out ByteBuf with specified hexString converted
88      */
89     public static void hexStringToByteBuf(String hexSrc, ByteBuf out) {
90         out.writeBytes(hexStringToBytes(hexSrc));
91     }
92     
93     /**
94      * Fills specified ByteBuf with 0 (zeros) of desired length, used for padding
95      * @param length
96      * @param out ByteBuf to be padded
97      */
98     public static void padBuffer(int length, ByteBuf out) {
99         for (int i = 0; i < length; i++) {
100             out.writeByte(0);
101         }
102     }
103     
104     
105     /**
106      * Create standard OF header
107      * @param msgType message code
108      * @param message POJO
109      * @param out writing buffer
110      * @param length ofheader length
111      */
112     public static <E extends OfHeader> void writeOFHeader(byte msgType, E message, ByteBuf out, int length) { 
113         out.writeByte(message.getVersion());
114         out.writeByte(msgType);
115         out.writeShort(length);
116         out.writeInt(message.getXid().intValue());
117     }
118     
119     /**
120      * Write length standard OF header
121      * @param out writing buffer
122      */
123     public static void updateOFHeaderLength(ByteBuf out) { 
124         out.setShort(EncodeConstants.OFHEADER_LENGTH_INDEX, out.readableBytes());
125     }
126
127     /**
128      * Fills the bitmask from boolean map where key is bit position
129      * @param booleanMap bit to boolean mapping
130      * @return bit mask
131      */
132     public static int fillBitMaskFromMap(Map<Integer, Boolean> booleanMap) {
133         int bitmask = 0;
134         
135         for (Entry<Integer, Boolean> iterator : booleanMap.entrySet()) {
136             if (iterator.getValue() != null && iterator.getValue().booleanValue()) {
137                 bitmask |= 1 << iterator.getKey();
138             }
139         }
140         return bitmask;
141     }
142     
143     /**
144      * Fills the bitmask from boolean list where key is bit position
145      * @param booleanList bit to boolean mapping
146      * @return bit mask
147      */
148     public static int[] fillBitMaskFromList(List<Boolean> booleanList) {
149         int[] bitmask;
150         int index = 0;
151         int arrayIndex = 0;
152         if ((booleanList.size() % Integer.SIZE) != 0) {
153             bitmask = new int[booleanList.size() / Integer.SIZE + 1];
154         } else {
155             bitmask = new int[booleanList.size() / Integer.SIZE];
156         }
157         for (Boolean currElement : booleanList) {
158             if (currElement != null && currElement.booleanValue()) {
159                 bitmask[arrayIndex] |= 1 << index;
160             }
161             index++;
162             arrayIndex = index / Integer.SIZE;
163         }
164         return bitmask;
165     }
166
167     /**
168      * Converts byte array into String
169      * @param array input byte array
170      * @return String
171      */
172     public static String bytesToHexString(byte[] array) {
173         StringBuffer sb = new StringBuffer();
174         for (int i = 0; i < array.length; i++) {
175             sb.append(String.format(" %02x", array[i]));
176         }
177         return sb.toString().trim();
178     }
179     
180     /**
181      * Converts macAddress to byte array
182      * @param macAddress
183      * @return byte representation of mac address
184      * @see {@link MacAddress}
185      */
186     @SuppressWarnings("javadoc")
187     public static byte[] macAddressToBytes(String macAddress) {
188         String[] sequences = macAddress.split(":");
189         byte[] result = new byte[EncodeConstants.MAC_ADDRESS_LENGTH];
190         for (int i = 0; i < sequences.length; i++) {
191              result[i] = (byte) Short.parseShort(sequences[i], 16);
192         }
193         return result;
194     }
195     
196     /**
197      * Converts mac address represented in bytes to String
198      * @param address
199      * @return String representation of mac address
200      * @see {@link MacAddress}
201      */
202     @SuppressWarnings("javadoc")
203     public static String macAddressToString(byte[] address) {
204         List<String> groups = new ArrayList<>();
205         for(int i=0; i < EncodeConstants.MAC_ADDRESS_LENGTH; i++){
206             groups.add(String.format("%02X", address[i]));
207         }
208         Joiner joiner = Joiner.on(":");
209         return joiner.join(groups); 
210     }
211     
212     /**
213      * Reads and parses null-terminated string from ByteBuf
214      * @param rawMessage
215      * @param length maximal length of String
216      * @return String with name of port
217      */
218     public static String decodeNullTerminatedString(ByteBuf rawMessage, int length) {
219         byte[] name = new byte[length];
220         rawMessage.readBytes(name);
221         return new String(name).trim();
222     }
223     
224 }