1#!/usr/bin/env python
2#
3# This code is derived from GensrcBuffer.gmk which carries the following copyright.
4#
5# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
6# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7#
8# This code is free software; you can redistribute it and/or modify it
9# under the terms of the GNU General Public License version 2 only, as
10# published by the Free Software Foundation.  Oracle designates this
11# particular file as subject to the "Classpath" exception as provided
12# by Oracle in the LICENSE file that accompanied this code.
13#
14# This code is distributed in the hope that it will be useful, but WITHOUT
15# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
17# version 2 for more details (a copy is included in the LICENSE file that
18# accompanied this code).
19#
20# You should have received a copy of the GNU General Public License version
21# 2 along with this work; if not, write to the Free Software Foundation,
22# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
23#
24# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
25# or visit www.oracle.com if you need additional information or have any
26# questions.
27#
28
29"""
30Prints out the commands for generating the buffer classes in the java.nio package from templates.
31
32Run with "gen_java_nio.py <input directory> <output directory>"
33
34"""
35
36from enum import Enum, auto
37import math
38import os.path
39import argparse
40import sys
41
42PRIMITIVE_BYTE = "byte"
43PRIMITIVE_CHAR = "char"
44PRIMITIVE_SHORT = "short"
45PRIMITIVE_INT = "int"
46PRIMITIVE_LONG = "long"
47PRIMITIVE_FLOAT = "float"
48PRIMITIVE_DOUBLE = "double"
49
50PRIMITIVE_TO_BUFFER_PREFIX = {
51    PRIMITIVE_BYTE: "Byte",
52    PRIMITIVE_CHAR: "Char",
53    PRIMITIVE_SHORT: "Short",
54    PRIMITIVE_INT: "Int",
55    PRIMITIVE_LONG: "Long",
56    PRIMITIVE_FLOAT: "Float",
57    PRIMITIVE_DOUBLE: "Double",
58}
59
60PRIMITIVES = PRIMITIVE_TO_BUFFER_PREFIX.keys()
61
62PRIMITIVE_TO_REFERENCE_TYPE = {
63    PRIMITIVE_BYTE: "Byte",
64    PRIMITIVE_CHAR: "Character",
65    PRIMITIVE_SHORT: "Short",
66    PRIMITIVE_INT: "Integer",
67    PRIMITIVE_LONG: "Long",
68    PRIMITIVE_FLOAT: "Float",
69    PRIMITIVE_DOUBLE: "Double",
70}
71
72PRIMITIVE_TO_BYTES_PER_VALUE = {
73    PRIMITIVE_BYTE: 1,
74    PRIMITIVE_CHAR: 2,
75    PRIMITIVE_SHORT: 2,
76    PRIMITIVE_INT: 4,
77    PRIMITIVE_LONG: 8,
78    PRIMITIVE_FLOAT: 4,
79    PRIMITIVE_DOUBLE: 8,
80}
81
82BYTE_ORDER_DEFAULT = ""
83BYTE_ORDER_LITTLE_ENDIAN = "L"
84BYTE_ORDER_BIG_ENDIAN = "B"
85BYTE_ORDER_UNSWAPPED = "U"
86BYTE_ORDER_SWAPPED = "S"
87
88SPP = "java build.tools.spp.Spp "
89
90def generate_buffer(template_file, output_file, primitive_type,
91                    bin_ops="", read_only=False, byte_order=BYTE_ORDER_DEFAULT, append=" > "):
92    # fixRW
93    the_rw_key = "ro" if read_only else "rw"
94
95    # typesAndBits
96    the_a = "a"
97    the_A = "A"
98    the_x = primitive_type[0]
99    the_Type = primitive_type
100    the_type = the_Type.lower()
101    the_Fulltype = PRIMITIVE_TO_REFERENCE_TYPE[primitive_type.lower()]
102    the_fulltype = the_Fulltype.lower()
103    the_category = "integralType"
104    the_streams = ""
105    the_streamtype = ""
106    the_Streamtype = ""
107    the_BPV = PRIMITIVE_TO_BYTES_PER_VALUE[primitive_type.lower()]
108    the_LBPV = math.log2(the_BPV)
109    the_RW = "R" if read_only else ""
110
111    if primitive_type == PRIMITIVE_CHAR:
112        the_streams = "streamableType"
113        the_streamtype = "int"
114        the_Streamtype = "Int"
115    elif primitive_type == PRIMITIVE_INT:
116        the_a = "an"
117        the_A = "An"
118    elif primitive_type == PRIMITIVE_FLOAT or primitive_type == PRIMITIVE_DOUBLE:
119        the_category = "floatingPointType"
120
121    the_Swaptype = the_Type
122    the_memType = the_type
123    the_MemType = the_Type
124    the_fromBits = ""
125    the_toBits = ""
126    if primitive_type == PRIMITIVE_FLOAT:
127        the_fromBits = "Float.intBitsToFloat"
128        the_toBits = "Float.floatToRawIntBits"
129    elif primitive_type == PRIMITIVE_DOUBLE:
130        the_fromBits = "Double.longBitsToDouble"
131        the_toBits = "Double.doubleToRawLongBits"
132
133    the_swap = ""
134
135    command = SPP
136    command = command + " -K" + the_type
137    command = command + " -K" + the_category
138    command = command + " -K" + the_streams
139    command = command + " -Dtype=" + the_type
140    command = command + " -DType=" + the_Type
141    command = command + " -Dfulltype=" + the_fulltype
142    command = command + " -DFulltype=" + the_Fulltype
143    command = command + " -Dstreamtype=" + the_streamtype
144    command = command + " -DStreamtype=" + the_Streamtype
145    command = command + " -Dx=" + the_x
146    command = command + " -Dmemtype=" + the_memType
147    command = command + " -DMemtype=" + the_MemType
148    command = command + " -DSwaptype=" + the_Swaptype
149    command = command + " -DfromBits=" + the_fromBits
150    command = command + " -DtoBits=" + the_toBits
151    command = command + " -DLG_BYTES_PER_VALUE=" + str(the_LBPV)
152    command = command + " -DBYTES_PER_VALUE=" + str(the_BPV)
153    command = command + " -DBO=" + byte_order
154    command = command + " -Dswap=" + the_swap
155    command = command + " -DRW=" + the_RW
156    command = command + " -K" + the_rw_key
157    command = command + " -Da=" + the_a
158    command = command + " -DA=" + the_A
159    if (append == " >> "):
160        command = command + " -be"
161    if byte_order:
162        command = command + " -Kbo" + byte_order
163    command = command + " < " + template_file
164    command = command + append + output_file
165    print(command)
166
167    if bin_ops:
168        for primitive in PRIMITIVES:
169            if (primitive == PRIMITIVE_BYTE): continue
170            buffer_prefix = PRIMITIVE_TO_BUFFER_PREFIX[primitive]
171            generate_buffer(bin_ops, output_file, buffer_prefix, "", False, "", " >> ")
172
173
174
175def iterate_through_primitives(input_dir, output_dir, template_name, output_name, byte_order):
176    for primitive in PRIMITIVES:
177        if (primitive == PRIMITIVE_BYTE): continue
178        buffer_prefix = PRIMITIVE_TO_BUFFER_PREFIX[primitive]
179        template_file = os.path.join(input_dir, template_name)
180        output_file = os.path.join(output_dir, output_name + buffer_prefix + "Buffer" + byte_order + ".java")
181        output_file_r = os.path.join(output_dir, output_name + buffer_prefix + "BufferR" + byte_order + ".java")
182        generate_buffer(template_file, output_file, buffer_prefix, "", False, byte_order)
183        print("\n")
184        generate_buffer(template_file, output_file_r, buffer_prefix, "", True, byte_order)
185        print("\n")
186
187    # Generate X-Buffers
188def main():
189    parser = argparse.ArgumentParser(
190        description='Parse input and output directories')
191    parser.add_argument('input', help='Path to the directory that contains the template files')
192    parser.add_argument('output', help='Path to the directory where the output files should be placed')
193    args = parser.parse_args()
194
195    template_dir = args.input
196    output_dir = args.output
197    print("\nX-Buffer\n")
198
199    for primitive in PRIMITIVES:
200        bin_ops = os.path.join(template_dir, "X-Buffer-bin.java.template") if primitive == PRIMITIVE_BYTE else ""
201        buffer_prefix = PRIMITIVE_TO_BUFFER_PREFIX[primitive]
202        template_file = os.path.join(template_dir, "X-Buffer.java.template")
203        output_file = os.path.join(output_dir, buffer_prefix + "Buffer.java")
204        generate_buffer(template_file, output_file, buffer_prefix, bin_ops)
205        print("\n")
206
207    print("\nHeap-X-Buffer\n")
208
209    for primitive in PRIMITIVES:
210        buffer_prefix = PRIMITIVE_TO_BUFFER_PREFIX[primitive]
211        template_file = os.path.join(template_dir, "Heap-X-Buffer.java.template")
212        output_file = os.path.join(output_dir, "Heap" + buffer_prefix + "Buffer.java")
213        output_file_r = os.path.join(output_dir, "Heap" + buffer_prefix + "BufferR.java")
214        generate_buffer(template_file, output_file, buffer_prefix, "")
215        print("\n")
216        generate_buffer(template_file, output_file_r, buffer_prefix, "", True)
217        print("\n")
218
219    print("\nDirect-X-Buffer\n")
220
221    generate_buffer(os.path.join(template_dir, "Direct-X-Buffer.java.template"),
222        os.path.join(output_dir, "DirectByteBuffer.java"), "Byte",
223        os.path.join(template_dir, "Direct-X-Buffer-bin.java.template"))
224    print("\n")
225    generate_buffer(os.path.join(template_dir, "Direct-X-Buffer.java.template"),
226        os.path.join(output_dir, "DirectByteBufferR.java"), "Byte",
227        os.path.join(template_dir, "Direct-X-Buffer-bin.java.template"), True)
228    print("\n")
229
230    print("\nDirect-X-Buffer Unswapped\n")
231
232    iterate_through_primitives(template_dir, output_dir, "Direct-X-Buffer.java.template", "Direct", "U")
233
234    print("\nDirect-X-Buffer Swapped\n")
235
236    iterate_through_primitives(template_dir, output_dir, "Direct-X-Buffer.java.template", "Direct", "S")
237
238    print("\nByteBufferAs-X-Buffer BigEndian\n")
239
240    iterate_through_primitives(template_dir, output_dir, "ByteBufferAs-X-Buffer.java.template", "ByteBufferAs", "B")
241
242    print("\nByteBufferAs-X-Buffer LittleEndian\n")
243
244    iterate_through_primitives(template_dir, output_dir, "ByteBufferAs-X-Buffer.java.template", "ByteBufferAs", "L")
245
246    print("\nDONE\n")
247
248
249main()