123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226 |
- // Protocol Buffers - Google's data interchange format
- // Copyright 2008 Google Inc. All rights reserved.
- // https://developers.google.com/protocol-buffers/
- //
- // Redistribution and use in source and binary forms, with or without
- // modification, are permitted provided that the following conditions are
- // met:
- //
- // * Redistributions of source code must retain the above copyright
- // notice, this list of conditions and the following disclaimer.
- // * Redistributions in binary form must reproduce the above
- // copyright notice, this list of conditions and the following disclaimer
- // in the documentation and/or other materials provided with the
- // distribution.
- // * Neither the name of Google Inc. nor the names of its
- // contributors may be used to endorse or promote products derived from
- // this software without specific prior written permission.
- //
- // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- #include "names.h"
- #include <stdlib.h>
- #include "protobuf.h"
- /* stringsink *****************************************************************/
- typedef struct {
- char *ptr;
- size_t len, size;
- } stringsink;
- static size_t stringsink_string(stringsink *sink, const char *ptr, size_t len) {
- size_t new_size = sink->size;
- while (sink->len + len > new_size) {
- new_size *= 2;
- }
- if (new_size != sink->size) {
- sink->ptr = realloc(sink->ptr, new_size);
- sink->size = new_size;
- }
- memcpy(sink->ptr + sink->len, ptr, len);
- sink->len += len;
- return len;
- }
- static void stringsink_init(stringsink *sink) {
- sink->size = 32;
- sink->ptr = malloc(sink->size);
- PBPHP_ASSERT(sink->ptr != NULL);
- sink->len = 0;
- }
- static void stringsink_uninit(stringsink *sink) { free(sink->ptr); }
- /* def name -> classname ******************************************************/
- const char *const kReservedNames[] = {
- "abstract", "and", "array", "as", "break",
- "callable", "case", "catch", "class", "clone",
- "const", "continue", "declare", "default", "die",
- "do", "echo", "else", "elseif", "empty",
- "enddeclare", "endfor", "endforeach", "endif", "endswitch",
- "endwhile", "eval", "exit", "extends", "final",
- "for", "foreach", "function", "global", "goto",
- "if", "implements", "include", "include_once", "instanceof",
- "insteadof", "interface", "isset", "list", "namespace",
- "new", "or", "print", "private", "protected",
- "public", "require", "require_once", "return", "static",
- "switch", "throw", "trait", "try", "unset",
- "use", "var", "while", "xor", "int",
- "float", "bool", "string", "true", "false",
- "null", "void", "iterable", NULL};
- bool is_reserved_name(const char* name) {
- int i;
- for (i = 0; kReservedNames[i]; i++) {
- if (strcmp(kReservedNames[i], name) == 0) {
- return true;
- }
- }
- return false;
- }
- static char nolocale_tolower(char ch) {
- if (ch >= 'A' && ch <= 'Z') {
- return ch - ('A' - 'a');
- } else {
- return ch;
- }
- }
- static char nolocale_toupper(char ch) {
- if (ch >= 'a' && ch <= 'z') {
- return ch - ('a' - 'A');
- } else {
- return ch;
- }
- }
- static bool is_reserved(const char *segment, int length) {
- bool result;
- char* lower = calloc(1, length + 1);
- memcpy(lower, segment, length);
- int i = 0;
- while(lower[i]) {
- lower[i] = nolocale_tolower(lower[i]);
- i++;
- }
- lower[length] = 0;
- result = is_reserved_name(lower);
- free(lower);
- return result;
- }
- static void fill_prefix(const char *segment, int length,
- const char *prefix_given,
- const char *package_name,
- stringsink *classname) {
- if (prefix_given != NULL && strcmp(prefix_given, "") != 0) {
- stringsink_string(classname, prefix_given, strlen(prefix_given));
- } else {
- if (is_reserved(segment, length)) {
- if (package_name != NULL &&
- strcmp("google.protobuf", package_name) == 0) {
- stringsink_string(classname, "GPB", 3);
- } else {
- stringsink_string(classname, "PB", 2);
- }
- }
- }
- }
- static void fill_segment(const char *segment, int length,
- stringsink *classname, bool use_camel) {
- if (use_camel && (segment[0] < 'A' || segment[0] > 'Z')) {
- char first = nolocale_toupper(segment[0]);
- stringsink_string(classname, &first, 1);
- stringsink_string(classname, segment + 1, length - 1);
- } else {
- stringsink_string(classname, segment, length);
- }
- }
- static void fill_namespace(const char *package, const char *php_namespace,
- stringsink *classname) {
- if (php_namespace != NULL) {
- if (strlen(php_namespace) != 0) {
- stringsink_string(classname, php_namespace, strlen(php_namespace));
- stringsink_string(classname, "\\", 1);
- }
- } else if (package != NULL) {
- int i = 0, j = 0;
- size_t package_len = strlen(package);
- while (i < package_len) {
- j = i;
- while (j < package_len && package[j] != '.') {
- j++;
- }
- fill_prefix(package + i, j - i, "", package, classname);
- fill_segment(package + i, j - i, classname, true);
- stringsink_string(classname, "\\", 1);
- i = j + 1;
- }
- }
- }
- static void fill_classname(const char *fullname,
- const char *package,
- const char *prefix,
- stringsink *classname) {
- int classname_start = 0;
- if (package != NULL) {
- size_t package_len = strlen(package);
- classname_start = package_len == 0 ? 0 : package_len + 1;
- }
- size_t fullname_len = strlen(fullname);
- int i = classname_start, j;
- while (i < fullname_len) {
- j = i;
- while (j < fullname_len && fullname[j] != '.') {
- j++;
- }
- fill_prefix(fullname + i, j - i, prefix, package, classname);
- fill_segment(fullname + i, j - i, classname, false);
- if (j != fullname_len) {
- stringsink_string(classname, "\\", 1);
- }
- i = j + 1;
- }
- }
- char *GetPhpClassname(const upb_filedef *file, const char *fullname) {
- // Prepend '.' to package name to make it absolute. In the 5 additional
- // bytes allocated, one for '.', one for trailing 0, and 3 for 'GPB' if
- // given message is google.protobuf.Empty.
- const char *package = upb_filedef_package(file);
- const char *php_namespace = upb_filedef_phpnamespace(file);
- const char *prefix = upb_filedef_phpprefix(file);
- char *ret;
- stringsink namesink;
- stringsink_init(&namesink);
- fill_namespace(package, php_namespace, &namesink);
- fill_classname(fullname, package, prefix, &namesink);
- stringsink_string(&namesink, "\0", 1);
- ret = strdup(namesink.ptr);
- stringsink_uninit(&namesink);
- return ret;
- }
|