| """Starlark helpers for Objective-C protos.""" | |
| # State constants for objc_proto_camel_case_name. | |
| _last_was_other = 0 | |
| _last_was_lowercase = 1 | |
| _last_was_uppercase = 2 | |
| _last_was_number = 3 | |
| def objc_proto_camel_case_name(name): | |
| """A Starlark version of the ObjC generator's CamelCase name transform. | |
| This needs to track | |
| src/google/protobuf/compiler/objectivec/names.cc's UnderscoresToCamelCase() | |
| NOTE: This code is written to model the C++ in protoc's ObjC generator so it | |
| is easier to confirm that the algorithms between the implementations match. | |
| The customizations for starlark performance are: | |
| - The cascade within the loop is reordered and special cases "_" to | |
| optimize for google3 inputs. | |
| - The "last was" state is handled via integers instead of three booleans. | |
| The `first_capitalized` argument in the C++ code is left off this code and | |
| it acts as if the value were `True`. | |
| Args: | |
| name: The proto file name to convert to camel case. The extension should | |
| already be removed. | |
| Returns: | |
| The converted proto name to camel case. | |
| """ | |
| segments = [] | |
| current = "" | |
| last_was = _last_was_other | |
| for c in name.elems(): | |
| if c.islower(): | |
| # lowercase letter can follow a lowercase or uppercase letter. | |
| if last_was != _last_was_lowercase and last_was != _last_was_uppercase: | |
| segments.append(current) | |
| current = c.upper() | |
| else: | |
| current += c | |
| last_was = _last_was_lowercase | |
| elif c == "_": # more common than rest, special case it. | |
| last_was = _last_was_other | |
| elif c.isdigit(): | |
| if last_was != _last_was_number: | |
| segments.append(current) | |
| current = "" | |
| current += c | |
| last_was = _last_was_number | |
| elif c.isupper(): | |
| if last_was != _last_was_uppercase: | |
| segments.append(current) | |
| current = c | |
| else: | |
| current += c.lower() | |
| last_was = _last_was_uppercase | |
| else: | |
| last_was = _last_was_other | |
| segments.append(current) | |
| result = "" | |
| for x in segments: | |
| if x in ("Url", "Http", "Https"): | |
| result += x.upper() | |
| else: | |
| result += x | |
| return result |