xref: /aosp_15_r20/external/cronet/third_party/jni_zero/common.py (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker# Copyright 2023 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker# found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker"""Common logic needed by other modules."""
5*6777b538SAndroid Build Coastguard Worker
6*6777b538SAndroid Build Coastguard Workerimport contextlib
7*6777b538SAndroid Build Coastguard Workerimport filecmp
8*6777b538SAndroid Build Coastguard Workerimport os
9*6777b538SAndroid Build Coastguard Workerimport shutil
10*6777b538SAndroid Build Coastguard Workerimport tempfile
11*6777b538SAndroid Build Coastguard Workerimport pathlib
12*6777b538SAndroid Build Coastguard Workerimport zipfile
13*6777b538SAndroid Build Coastguard Worker
14*6777b538SAndroid Build Coastguard Worker
15*6777b538SAndroid Build Coastguard Worker# Only some methods respect line length, so this is more of a best-effort
16*6777b538SAndroid Build Coastguard Worker# limit.
17*6777b538SAndroid Build Coastguard Worker_TARGET_LINE_LENGTH = 80
18*6777b538SAndroid Build Coastguard Worker
19*6777b538SAndroid Build Coastguard Worker
20*6777b538SAndroid Build Coastguard Workerclass StringBuilder:
21*6777b538SAndroid Build Coastguard Worker
22*6777b538SAndroid Build Coastguard Worker  def __init__(self):
23*6777b538SAndroid Build Coastguard Worker    self._sb = []
24*6777b538SAndroid Build Coastguard Worker    self._indent = 0
25*6777b538SAndroid Build Coastguard Worker    self._start_of_line = True
26*6777b538SAndroid Build Coastguard Worker
27*6777b538SAndroid Build Coastguard Worker  def __call__(self, value):
28*6777b538SAndroid Build Coastguard Worker    lines = value.splitlines(keepends=True)
29*6777b538SAndroid Build Coastguard Worker    for line in lines:
30*6777b538SAndroid Build Coastguard Worker      if self._start_of_line and line != '\n':
31*6777b538SAndroid Build Coastguard Worker        self._sb.append(' ' * self._indent)
32*6777b538SAndroid Build Coastguard Worker      self._sb.append(line)
33*6777b538SAndroid Build Coastguard Worker      self._start_of_line = line[-1] == '\n'
34*6777b538SAndroid Build Coastguard Worker
35*6777b538SAndroid Build Coastguard Worker  def _cur_line_length(self):
36*6777b538SAndroid Build Coastguard Worker    ret = 0
37*6777b538SAndroid Build Coastguard Worker    for l in reversed(self._sb):
38*6777b538SAndroid Build Coastguard Worker      if l.endswith('\n'):
39*6777b538SAndroid Build Coastguard Worker        break
40*6777b538SAndroid Build Coastguard Worker      ret += len(l)
41*6777b538SAndroid Build Coastguard Worker    return ret
42*6777b538SAndroid Build Coastguard Worker
43*6777b538SAndroid Build Coastguard Worker  @contextlib.contextmanager
44*6777b538SAndroid Build Coastguard Worker  def _param_list_generator(self):
45*6777b538SAndroid Build Coastguard Worker    values = []
46*6777b538SAndroid Build Coastguard Worker    yield values
47*6777b538SAndroid Build Coastguard Worker    self.param_list(values)
48*6777b538SAndroid Build Coastguard Worker
49*6777b538SAndroid Build Coastguard Worker  def param_list(self, values=None):
50*6777b538SAndroid Build Coastguard Worker    if values is None:
51*6777b538SAndroid Build Coastguard Worker      return self._param_list_generator()
52*6777b538SAndroid Build Coastguard Worker
53*6777b538SAndroid Build Coastguard Worker    self('(')
54*6777b538SAndroid Build Coastguard Worker    punctuation_size = 2 * len(values) # punctuation: ", ()"
55*6777b538SAndroid Build Coastguard Worker    single_line_size = sum(len(v) for v in values) + punctuation_size
56*6777b538SAndroid Build Coastguard Worker    if self._cur_line_length() + single_line_size < _TARGET_LINE_LENGTH:
57*6777b538SAndroid Build Coastguard Worker      self(', '.join(values))
58*6777b538SAndroid Build Coastguard Worker    else:
59*6777b538SAndroid Build Coastguard Worker      self('\n')
60*6777b538SAndroid Build Coastguard Worker      with self.indent(4):
61*6777b538SAndroid Build Coastguard Worker        self(',\n'.join(values))
62*6777b538SAndroid Build Coastguard Worker    self(')')
63*6777b538SAndroid Build Coastguard Worker
64*6777b538SAndroid Build Coastguard Worker  @contextlib.contextmanager
65*6777b538SAndroid Build Coastguard Worker  def statement(self):
66*6777b538SAndroid Build Coastguard Worker    yield
67*6777b538SAndroid Build Coastguard Worker    self(';\n')
68*6777b538SAndroid Build Coastguard Worker
69*6777b538SAndroid Build Coastguard Worker  @contextlib.contextmanager
70*6777b538SAndroid Build Coastguard Worker  def block(self):
71*6777b538SAndroid Build Coastguard Worker    self(' {\n')
72*6777b538SAndroid Build Coastguard Worker    with self.indent(2):
73*6777b538SAndroid Build Coastguard Worker      yield
74*6777b538SAndroid Build Coastguard Worker    self('}\n')
75*6777b538SAndroid Build Coastguard Worker
76*6777b538SAndroid Build Coastguard Worker  @contextlib.contextmanager
77*6777b538SAndroid Build Coastguard Worker  def indent(self, amount):
78*6777b538SAndroid Build Coastguard Worker    self._indent += amount
79*6777b538SAndroid Build Coastguard Worker    yield
80*6777b538SAndroid Build Coastguard Worker    self._indent -= amount
81*6777b538SAndroid Build Coastguard Worker
82*6777b538SAndroid Build Coastguard Worker  def to_string(self):
83*6777b538SAndroid Build Coastguard Worker    return ''.join(self._sb)
84*6777b538SAndroid Build Coastguard Worker
85*6777b538SAndroid Build Coastguard Worker
86*6777b538SAndroid Build Coastguard Workerdef capitalize(value):
87*6777b538SAndroid Build Coastguard Worker  return value[0].upper() + value[1:]
88*6777b538SAndroid Build Coastguard Worker
89*6777b538SAndroid Build Coastguard Worker
90*6777b538SAndroid Build Coastguard Workerdef escape_class_name(fully_qualified_class):
91*6777b538SAndroid Build Coastguard Worker  """Returns an escaped string concatenating the Java package and class."""
92*6777b538SAndroid Build Coastguard Worker  escaped = fully_qualified_class.replace('_', '_1')
93*6777b538SAndroid Build Coastguard Worker  return escaped.replace('/', '_').replace('$', '_00024')
94*6777b538SAndroid Build Coastguard Worker
95*6777b538SAndroid Build Coastguard Worker
96*6777b538SAndroid Build Coastguard Worker@contextlib.contextmanager
97*6777b538SAndroid Build Coastguard Workerdef atomic_output(path, mode='w+b'):
98*6777b538SAndroid Build Coastguard Worker  with tempfile.NamedTemporaryFile(mode, delete=False) as f:
99*6777b538SAndroid Build Coastguard Worker    try:
100*6777b538SAndroid Build Coastguard Worker      yield f
101*6777b538SAndroid Build Coastguard Worker    finally:
102*6777b538SAndroid Build Coastguard Worker      f.close()
103*6777b538SAndroid Build Coastguard Worker
104*6777b538SAndroid Build Coastguard Worker    if not (os.path.exists(path) and filecmp.cmp(f.name, path)):
105*6777b538SAndroid Build Coastguard Worker      pathlib.Path(path).parents[0].mkdir(parents=True, exist_ok=True)
106*6777b538SAndroid Build Coastguard Worker      shutil.move(f.name, path)
107*6777b538SAndroid Build Coastguard Worker    if os.path.exists(f.name):
108*6777b538SAndroid Build Coastguard Worker      os.unlink(f.name)
109*6777b538SAndroid Build Coastguard Worker
110*6777b538SAndroid Build Coastguard Worker
111*6777b538SAndroid Build Coastguard Workerdef add_to_zip_hermetic(zip_file, zip_path, data=None):
112*6777b538SAndroid Build Coastguard Worker  zipinfo = zipfile.ZipInfo(filename=zip_path)
113*6777b538SAndroid Build Coastguard Worker  zipinfo.external_attr = 0o644 << 16
114*6777b538SAndroid Build Coastguard Worker  zipinfo.date_time = (2001, 1, 1, 0, 0, 0)
115*6777b538SAndroid Build Coastguard Worker  zip_file.writestr(zipinfo, data, zipfile.ZIP_STORED)
116