19ae0b401654f2faf408bb37808e7f6a5ede976b6Adam Vartanian#!/usr/bin/env python 29ae0b401654f2faf408bb37808e7f6a5ede976b6Adam Vartanian# 39ae0b401654f2faf408bb37808e7f6a5ede976b6Adam Vartanian# Copyright (C) 2017 The Android Open Source Project 49ae0b401654f2faf408bb37808e7f6a5ede976b6Adam Vartanian# 59ae0b401654f2faf408bb37808e7f6a5ede976b6Adam Vartanian# Licensed under the Apache License, Version 2.0 (the "License"); 69ae0b401654f2faf408bb37808e7f6a5ede976b6Adam Vartanian# you may not use this file except in compliance with the License. 79ae0b401654f2faf408bb37808e7f6a5ede976b6Adam Vartanian# You may obtain a copy of the License at 89ae0b401654f2faf408bb37808e7f6a5ede976b6Adam Vartanian# 99ae0b401654f2faf408bb37808e7f6a5ede976b6Adam Vartanian# http://www.apache.org/licenses/LICENSE-2.0 109ae0b401654f2faf408bb37808e7f6a5ede976b6Adam Vartanian# 119ae0b401654f2faf408bb37808e7f6a5ede976b6Adam Vartanian# Unless required by applicable law or agreed to in writing, software 129ae0b401654f2faf408bb37808e7f6a5ede976b6Adam Vartanian# distributed under the License is distributed on an "AS IS" BASIS, 139ae0b401654f2faf408bb37808e7f6a5ede976b6Adam Vartanian# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 149ae0b401654f2faf408bb37808e7f6a5ede976b6Adam Vartanian# See the License for the specific language governing permissions and 159ae0b401654f2faf408bb37808e7f6a5ede976b6Adam Vartanian# limitations under the License. 169ae0b401654f2faf408bb37808e7f6a5ede976b6Adam Vartanian 179ae0b401654f2faf408bb37808e7f6a5ede976b6Adam Vartanian"""Outputs HTML based on an input JSON file. 189ae0b401654f2faf408bb37808e7f6a5ede976b6Adam Vartanian 199ae0b401654f2faf408bb37808e7f6a5ede976b6Adam VartanianOutputs HTML tables suitable for inclusion in the Android documentation that 209ae0b401654f2faf408bb37808e7f6a5ede976b6Adam Vartanianreflect the crypto algorithm support shown in the provided data file. 219ae0b401654f2faf408bb37808e7f6a5ede976b6Adam Vartanian""" 229ae0b401654f2faf408bb37808e7f6a5ede976b6Adam Vartanian 23748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanianimport argparse 24befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanianimport operator 259ae0b401654f2faf408bb37808e7f6a5ede976b6Adam Vartanian 26befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanianimport crypto_docs 27befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian 289ae0b401654f2faf408bb37808e7f6a5ede976b6Adam Vartanian 2922051136d1344e34c05659420bc49372040bd75eAdam Vartanianfind_by_name = crypto_docs.find_by_name 3022051136d1344e34c05659420bc49372040bd75eAdam Vartanian 3122051136d1344e34c05659420bc49372040bd75eAdam Vartanian 329ae0b401654f2faf408bb37808e7f6a5ede976b6Adam Vartaniandef sort_by_name(seq): 339ae0b401654f2faf408bb37808e7f6a5ede976b6Adam Vartanian return sorted(seq, key=lambda x: x['name']) 349ae0b401654f2faf408bb37808e7f6a5ede976b6Adam Vartanian 359ae0b401654f2faf408bb37808e7f6a5ede976b6Adam Vartanian 361179672f16736ef3437dd4603132c5f25809179dAdam Vartaniandef has_notes(category): 371179672f16736ef3437dd4603132c5f25809179dAdam Vartanian for algorithm in category['algorithms']: 381179672f16736ef3437dd4603132c5f25809179dAdam Vartanian if 'note' in algorithm: 391179672f16736ef3437dd4603132c5f25809179dAdam Vartanian return True 401179672f16736ef3437dd4603132c5f25809179dAdam Vartanian return False 411179672f16736ef3437dd4603132c5f25809179dAdam Vartanian 421179672f16736ef3437dd4603132c5f25809179dAdam Vartanian 431179672f16736ef3437dd4603132c5f25809179dAdam Vartanian# Prevents the given value from being word-wrapped. This is mainly to ensure that 441179672f16736ef3437dd4603132c5f25809179dAdam Vartanian# long identifiers with hyphens, like OAEPwithSHA-1andMGF1Padding, don't get word-wrapped 451179672f16736ef3437dd4603132c5f25809179dAdam Vartanian# at the hyphen. 461179672f16736ef3437dd4603132c5f25809179dAdam Vartaniandef nowrap(value): 471179672f16736ef3437dd4603132c5f25809179dAdam Vartanian return '<span style="white-space: nowrap">%s</span>' % value 481179672f16736ef3437dd4603132c5f25809179dAdam Vartanian 491179672f16736ef3437dd4603132c5f25809179dAdam Vartanian 509ae0b401654f2faf408bb37808e7f6a5ede976b6Adam Vartaniandef main(): 51748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian parser = argparse.ArgumentParser(description='Output algorithm support HTML tables') 52748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian parser.add_argument('--for_javadoc', 53748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian action='store_true', 54748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian help='If specified, format for inclusion in class documentation') 551179672f16736ef3437dd4603132c5f25809179dAdam Vartanian parser.add_argument('--category', 561179672f16736ef3437dd4603132c5f25809179dAdam Vartanian action='append', 571179672f16736ef3437dd4603132c5f25809179dAdam Vartanian help='The category to display, may be specified multiple times') 58748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian parser.add_argument('file', 59748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian help='The JSON file to use for data') 60748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian args = parser.parse_args() 61748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian 62748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian output = [] 63748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian data = crypto_docs.load_json(args.file) 649ae0b401654f2faf408bb37808e7f6a5ede976b6Adam Vartanian categories = sort_by_name(data['categories']) 65748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian output.append('<h2 id="SupportedAlgorithms">Supported Algorithms</h2>') 66748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian output.append('') 67748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian output.append('<ul>') 689ae0b401654f2faf408bb37808e7f6a5ede976b6Adam Vartanian for category in categories: 6922051136d1344e34c05659420bc49372040bd75eAdam Vartanian if not category['name'].endswith('.Enabled'): 7022051136d1344e34c05659420bc49372040bd75eAdam Vartanian output.append(' <li><a href="#Supported{name}">' 7122051136d1344e34c05659420bc49372040bd75eAdam Vartanian '<code>{name}</code></a></li>'.format(**category)) 72748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian output.append('</ul>') 739ae0b401654f2faf408bb37808e7f6a5ede976b6Adam Vartanian for category in categories: 741179672f16736ef3437dd4603132c5f25809179dAdam Vartanian if args.category and category['name'] not in args.category: 751179672f16736ef3437dd4603132c5f25809179dAdam Vartanian continue 761179672f16736ef3437dd4603132c5f25809179dAdam Vartanian show_notes = has_notes(category) 7722051136d1344e34c05659420bc49372040bd75eAdam Vartanian if category['name'].endswith('.Enabled'): 7822051136d1344e34c05659420bc49372040bd75eAdam Vartanian # These are handled in the "Supported" section below 7922051136d1344e34c05659420bc49372040bd75eAdam Vartanian continue 80befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian if category['name'] == 'Cipher': 81befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian # We display ciphers in a four-column table to conserve space and 82befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian # so that it's more comprehensible. To do this, we have to 83befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian # collapse all our ciphers into "equivalence classes" of a sort. 84befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian 85befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian # First, collect the relevant data for each algorithm into a tuple. 86befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian # The mode and padding are in lists because we are going to collapse 87befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian # multiple tuples with those in later steps. 88befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian algorithms = sort_by_name(category['algorithms']) 89befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian tuples = [] 90befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian for algorithm in algorithms: 91befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian name, mode, padding = algorithm['name'].split('/') 92befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian tuples.append(( 93befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian name, 94befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian [mode], 95befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian [padding], 96befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian algorithm['supported_api_levels'], 971179672f16736ef3437dd4603132c5f25809179dAdam Vartanian 'deprecated' in algorithm and algorithm['deprecated'], 981179672f16736ef3437dd4603132c5f25809179dAdam Vartanian algorithm.get('note', ''))) 99befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian # Sort the tuples by all items except padding, then collapse 100befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian # items with all non-padding values the same (which will always be 101befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian # neighboring items) into a single item. 102befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian tuples.sort(key=operator.itemgetter(0, 1, 3, 4)) 103befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian i = 0 104befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian while i < len(tuples) - 1: 105befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian if (tuples[i][0] == tuples[i+1][0] 106befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian and tuples[i][1] == tuples[i+1][1] 107befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian and tuples[i][3] == tuples[i+1][3] 1081179672f16736ef3437dd4603132c5f25809179dAdam Vartanian and tuples[i][4] == tuples[i+1][4] 1091179672f16736ef3437dd4603132c5f25809179dAdam Vartanian and tuples[i][5] == tuples[i+1][5]): 110befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian tuples[i][2].extend(tuples[i+1][2]) 111befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian del tuples[i+1] 112befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian else: 113befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian i += 1 114befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian # Do the same thing as above, but with modes. 115befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian tuples.sort(key=operator.itemgetter(0, 2, 3, 4)) 116befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian i = 0 117befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian while i < len(tuples) - 1: 118befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian if (tuples[i][0] == tuples[i+1][0] 119befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian and tuples[i][2] == tuples[i+1][2] 120befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian and tuples[i][3] == tuples[i+1][3] 1211179672f16736ef3437dd4603132c5f25809179dAdam Vartanian and tuples[i][4] == tuples[i+1][4] 1221179672f16736ef3437dd4603132c5f25809179dAdam Vartanian and tuples[i][5] == tuples[i+1][5]): 123befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian tuples[i][1].extend(tuples[i+1][1]) 124befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian del tuples[i+1] 125befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian else: 126befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian i += 1 127befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian # Display the table with rowspans for those entries where all the 128befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian # items have the same algorithm, mode, etc 129748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian output.append('<h3 id="Supported{name}">{name}</h3>'.format(**category)) 130748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian output.append('<table>') 131748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian output.append(' <thead>') 132748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian output.append(' <tr>') 133748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian output.append(' <th>Algorithm</th>') 134748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian output.append(' <th>Modes</th>') 135748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian output.append(' <th>Paddings</th>') 136748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian output.append(' <th>Supported API Levels</th>') 1371179672f16736ef3437dd4603132c5f25809179dAdam Vartanian if show_notes: 1381179672f16736ef3437dd4603132c5f25809179dAdam Vartanian output.append(' <th>Notes</th>') 139748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian output.append(' </tr>') 140748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian output.append(' </thead>') 141748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian output.append(' <tbody>') 142befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian tuples.sort(key=operator.itemgetter(0, 4, 1, 2, 3)) 143befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian i = 0 144befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian cur_deprecated = None 145befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian cur_algorithm = None 146befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian cur_mode = None 147befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian while i < len(tuples): 148befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian row = tuples[i] 149befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian if row[4] != cur_deprecated: 150befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian cur_deprecated = row[4] 1511179672f16736ef3437dd4603132c5f25809179dAdam Vartanian cur_note = row[5] 152befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian cur_algorithm = None 153befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian cur_mode = None 154befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian if cur_deprecated: 155748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian output.append(' <tr class="deprecated">') 156befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian else: 157748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian output.append(' <tr>') 158befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian if row[0] != cur_algorithm: 159befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian cur_algorithm = row[0] 160befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian cur_mode = None 161befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian j = i + 1 162befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian while (j < len(tuples) 163befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian and tuples[j][4] == cur_deprecated 1641179672f16736ef3437dd4603132c5f25809179dAdam Vartanian and tuples[j][5] == cur_note 165befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian and tuples[j][0] == cur_algorithm): 166befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian j += 1 167befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian rowspan = j - i 168befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian if rowspan > 1: 1691179672f16736ef3437dd4603132c5f25809179dAdam Vartanian output.append(' <td rowspan="%d">%s</td>' % (rowspan, nowrap(cur_algorithm))) 170befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian else: 1711179672f16736ef3437dd4603132c5f25809179dAdam Vartanian output.append(' <td>%s</td>' % nowrap(cur_algorithm)) 172befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian if row[1] != cur_mode: 173befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian cur_mode = row[1] 174befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian j = i + 1 175befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian while (j < len(tuples) 176befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian and tuples[j][4] == cur_deprecated 1771179672f16736ef3437dd4603132c5f25809179dAdam Vartanian and tuples[j][5] == cur_note 178befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian and tuples[j][0] == cur_algorithm 179befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian and tuples[j][1] == cur_mode): 180befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian j += 1 181befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian rowspan = j - i 1821179672f16736ef3437dd4603132c5f25809179dAdam Vartanian modestring = '<br>'.join([nowrap(x) for x in cur_mode]) 183befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian if rowspan > 1: 184748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian output.append(' <td rowspan="%d">%s</td>' % (rowspan, modestring)) 185befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian else: 186748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian output.append(' <td>%s</td>' % modestring) 1871179672f16736ef3437dd4603132c5f25809179dAdam Vartanian output.append(' <td>%s</td>' % '<br>'.join([nowrap(x) for x in row[2]])) 1881179672f16736ef3437dd4603132c5f25809179dAdam Vartanian output.append(' <td>%s</td>' % nowrap(row[3])) 1891179672f16736ef3437dd4603132c5f25809179dAdam Vartanian if show_notes: 1901179672f16736ef3437dd4603132c5f25809179dAdam Vartanian output.append(' <td>%s</td>' % row[5]) 191748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian output.append(' </tr>') 192befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian i += 1 193748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian output.append(' </tbody>') 194748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian output.append('</table>') 19522051136d1344e34c05659420bc49372040bd75eAdam Vartanian elif category['name'].endswith('.Supported'): 19622051136d1344e34c05659420bc49372040bd75eAdam Vartanian # Some categories come with a "Supported" and "Enabled" list, and we 19722051136d1344e34c05659420bc49372040bd75eAdam Vartanian # group those together in one table for display. Every entry that's enabled 19822051136d1344e34c05659420bc49372040bd75eAdam Vartanian # must be supported, so we can just look up the enabled version for each 19922051136d1344e34c05659420bc49372040bd75eAdam Vartanian # supported item 20022051136d1344e34c05659420bc49372040bd75eAdam Vartanian basename = category['name'][:-len('.Supported')] 20122051136d1344e34c05659420bc49372040bd75eAdam Vartanian supported = sort_by_name(category['algorithms']) 20222051136d1344e34c05659420bc49372040bd75eAdam Vartanian enabled = sort_by_name(find_by_name(categories, basename + '.Enabled')['algorithms']) 20322051136d1344e34c05659420bc49372040bd75eAdam Vartanian output.append('<h3 id="Supported{0}">{0}</h3>'.format(basename)) 20422051136d1344e34c05659420bc49372040bd75eAdam Vartanian output.append('<table>') 20522051136d1344e34c05659420bc49372040bd75eAdam Vartanian output.append(' <thead>') 20622051136d1344e34c05659420bc49372040bd75eAdam Vartanian output.append(' <tr>') 20722051136d1344e34c05659420bc49372040bd75eAdam Vartanian output.append(' <th>Algorithm</th>') 20822051136d1344e34c05659420bc49372040bd75eAdam Vartanian output.append(' <th>Supported API Levels</th>') 20922051136d1344e34c05659420bc49372040bd75eAdam Vartanian output.append(' <th>Enabled By Default</th>') 2101179672f16736ef3437dd4603132c5f25809179dAdam Vartanian if show_notes: 2111179672f16736ef3437dd4603132c5f25809179dAdam Vartanian output.append(' <th>Notes</th>') 21222051136d1344e34c05659420bc49372040bd75eAdam Vartanian output.append(' </tr>') 21322051136d1344e34c05659420bc49372040bd75eAdam Vartanian output.append(' </thead>') 21422051136d1344e34c05659420bc49372040bd75eAdam Vartanian output.append(' <tbody>') 21522051136d1344e34c05659420bc49372040bd75eAdam Vartanian for algorithm in supported: 21622051136d1344e34c05659420bc49372040bd75eAdam Vartanian if 'deprecated' in algorithm and algorithm['deprecated']: 21722051136d1344e34c05659420bc49372040bd75eAdam Vartanian output.append(' <tr class="deprecated">') 21822051136d1344e34c05659420bc49372040bd75eAdam Vartanian else: 21922051136d1344e34c05659420bc49372040bd75eAdam Vartanian output.append(' <tr>') 2201179672f16736ef3437dd4603132c5f25809179dAdam Vartanian output.append(' <td>%s</td>' % nowrap(algorithm['name'])) 2211179672f16736ef3437dd4603132c5f25809179dAdam Vartanian output.append(' <td>%s</td>' % nowrap(algorithm['supported_api_levels'])) 22222051136d1344e34c05659420bc49372040bd75eAdam Vartanian enabled_alg = find_by_name(enabled, algorithm['name']) 22322051136d1344e34c05659420bc49372040bd75eAdam Vartanian if enabled_alg is None: 22422051136d1344e34c05659420bc49372040bd75eAdam Vartanian output.append(' <td></td>') 22522051136d1344e34c05659420bc49372040bd75eAdam Vartanian else: 2261179672f16736ef3437dd4603132c5f25809179dAdam Vartanian output.append(' <td>%s</td>' % nowrap(enabled_alg['supported_api_levels'])) 2271179672f16736ef3437dd4603132c5f25809179dAdam Vartanian if show_notes: 2281179672f16736ef3437dd4603132c5f25809179dAdam Vartanian if 'note' in algorithm: 2291179672f16736ef3437dd4603132c5f25809179dAdam Vartanian output.append(' <td>%s</td>' % algorithm['note']) 2301179672f16736ef3437dd4603132c5f25809179dAdam Vartanian else: 2311179672f16736ef3437dd4603132c5f25809179dAdam Vartanian output.append(' <td></td>') 23222051136d1344e34c05659420bc49372040bd75eAdam Vartanian output.append(' </tr>') 23322051136d1344e34c05659420bc49372040bd75eAdam Vartanian output.append(' </tbody>') 23422051136d1344e34c05659420bc49372040bd75eAdam Vartanian output.append('</table>') 235befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian else: 236748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian output.append('<h3 id="Supported{name}">{name}</h3>'.format(**category)) 237748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian output.append('<table>') 238748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian output.append(' <thead>') 239748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian output.append(' <tr>') 240748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian output.append(' <th>Algorithm</th>') 241748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian output.append(' <th>Supported API Levels</th>') 2421179672f16736ef3437dd4603132c5f25809179dAdam Vartanian if show_notes: 2431179672f16736ef3437dd4603132c5f25809179dAdam Vartanian output.append(' <th>Notes</th>') 244748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian output.append(' </tr>') 245748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian output.append(' </thead>') 246748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian output.append(' <tbody>') 247befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian algorithms = sort_by_name(category['algorithms']) 248befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian for algorithm in algorithms: 249befc86a711b876ed6523fbe453dfa7a9adb345afAdam Vartanian if 'deprecated' in algorithm and algorithm['deprecated']: 250748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian output.append(' <tr class="deprecated">') 251748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian else: 252748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian output.append(' <tr>') 2531179672f16736ef3437dd4603132c5f25809179dAdam Vartanian output.append(' <td>%s</td>' % nowrap(algorithm['name'])) 2541179672f16736ef3437dd4603132c5f25809179dAdam Vartanian output.append(' <td>%s</td>' % nowrap(algorithm['supported_api_levels'])) 2551179672f16736ef3437dd4603132c5f25809179dAdam Vartanian if show_notes: 2561179672f16736ef3437dd4603132c5f25809179dAdam Vartanian if 'note' in algorithm: 2571179672f16736ef3437dd4603132c5f25809179dAdam Vartanian output.append(' <td>%s</td>' % algorithm['note']) 2581179672f16736ef3437dd4603132c5f25809179dAdam Vartanian else: 2591179672f16736ef3437dd4603132c5f25809179dAdam Vartanian output.append(' <td></td>') 260748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian output.append(' </tr>') 261748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian output.append(' </tbody>') 262748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian output.append('</table>') 263748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian if args.for_javadoc: 264748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian for i in range(len(output)): 265748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian output[i] = ' * ' + output[i] 266748190c9f4fb5171888cb0287adfb5b64f41607bAdam Vartanian print '\n'.join(output) 2679ae0b401654f2faf408bb37808e7f6a5ede976b6Adam Vartanian 2689ae0b401654f2faf408bb37808e7f6a5ede976b6Adam Vartanian 2699ae0b401654f2faf408bb37808e7f6a5ede976b6Adam Vartanianif __name__ == '__main__': 2709ae0b401654f2faf408bb37808e7f6a5ede976b6Adam Vartanian main() 271