1 /*
  2  * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  */
 23 package org.openjdk.asmtools.jasm;
 24 
 25 import java.io.IOException;
 26 import java.util.ArrayList;
 27 import java.util.List;
 28 
 29 import static org.openjdk.asmtools.jasm.RuntimeConstants.*;
 30 
 31 /**
 32  * The record attribute (JEP 359 since class file 58.65535)
 33  */
 34 public class RecordData extends AttrData {
 35     private List<ComponentData> components = new ArrayList<>();
 36 
 37     public RecordData(ClassData cls) {
 38         super(cls, Tables.AttrTag.ATT_Record.parsekey());
 39     }
 40 
 41     public void addComponent(ConstantPool.ConstCell nameCell,
 42                              ConstantPool.ConstCell descCell,
 43                              ConstantPool.ConstCell signature,
 44                              ArrayList<AnnotationData> annotations) {
 45         // Define a field if absent
 46         FieldData fd = getClassData().addFieldIfAbsent(ACC_MANDATED & ACC_PRIVATE & ACC_FINAL, nameCell, descCell);
 47         ComponentData cd = new ComponentData(fd);
 48         if( annotations != null ) {
 49             cd.addAnnotations(annotations);
 50         }
 51         if( signature != null ) {
 52             cd.setSignatureAttr(signature);
 53         }
 54         components.add(cd);
 55     }
 56 
 57     public boolean isEmpty() {
 58         return components.isEmpty();
 59     }
 60 
 61     @Override
 62     public void write(CheckedDataOutputStream out) throws IOException {
 63         super.write(out);
 64         out.writeShort(components.size());
 65         for (ComponentData cd : components) {
 66             cd.write(out);
 67         }
 68     }
 69 
 70     @Override
 71     public int attrLength() {
 72         int compsLength = components.stream().mapToInt(c -> c.getLength()).sum();
 73         return 2 + compsLength;
 74     }
 75 
 76     class ComponentData extends MemberData {
 77         private FieldData field;
 78 
 79         public ComponentData(FieldData field) {
 80             super(getClassData());
 81             this.field = field;
 82         }
 83 
 84         @Override
 85         protected DataVector getAttrVector() {
 86             return getDataVector(signatureAttr);
 87         }
 88 
 89         public void write(CheckedDataOutputStream out) throws IOException, Parser.CompilerError {
 90             out.writeShort(field.getNameDesc().left.arg);
 91             out.writeShort(field.getNameDesc().right.arg);
 92             DataVector attrs = getAttrVector();
 93             attrs.write(out);
 94         }
 95 
 96         public int getLength() {
 97             return 4 + getAttrVector().getLength();
 98         }
 99     }
100 }