Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 2 additions & 6 deletions cpp/src/phonenumbers/alternate_format.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1589,12 +1589,8 @@ static const unsigned char data[] = {
};
} // namespace

int alternate_format_size() {
return sizeof(data) / sizeof(data[0]);
}

const void* alternate_format_get() {
return data;
MetadataBytes GetAlternateFormat() {
return MetadataBytes(data, sizeof(data) / sizeof(data[0]));
}

} // namespace phonenumbers
Expand Down
7 changes: 5 additions & 2 deletions cpp/src/phonenumbers/alternate_format.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,14 @@
#ifndef I18N_PHONENUMBERS_ALTERNATE_FORMAT_H_
#define I18N_PHONENUMBERS_ALTERNATE_FORMAT_H_

#include "phonenumbers/metadata_bytes.h"

namespace i18n {
namespace phonenumbers {

int alternate_format_size();
const void* alternate_format_get();
// Returns the serialized alternate-format PhoneMetadataCollection used by
// PhoneNumberMatcher. See metadata_bytes.h for ownership semantics.
MetadataBytes GetAlternateFormat();

} // namespace phonenumbers
} // namespace i18n
Expand Down
8 changes: 2 additions & 6 deletions cpp/src/phonenumbers/lite_metadata.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14740,12 +14740,8 @@ static const unsigned char data[] = {
};
} // namespace

int metadata_size() {
return sizeof(data) / sizeof(data[0]);
}

const void* metadata_get() {
return data;
MetadataBytes GetMetadata() {
return MetadataBytes(data, sizeof(data) / sizeof(data[0]));
}

} // namespace phonenumbers
Expand Down
8 changes: 2 additions & 6 deletions cpp/src/phonenumbers/metadata.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15681,12 +15681,8 @@ static const unsigned char data[] = {
};
} // namespace

int metadata_size() {
return sizeof(data) / sizeof(data[0]);
}

const void* metadata_get() {
return data;
MetadataBytes GetMetadata() {
return MetadataBytes(data, sizeof(data) / sizeof(data[0]));
}

} // namespace phonenumbers
Expand Down
8 changes: 6 additions & 2 deletions cpp/src/phonenumbers/metadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,15 @@
#ifndef I18N_PHONENUMBERS_METADATA_H_
#define I18N_PHONENUMBERS_METADATA_H_

#include "phonenumbers/metadata_bytes.h"

namespace i18n {
namespace phonenumbers {

int metadata_size();
const void* metadata_get();
// Returns the serialized PhoneMetadataCollection used by PhoneNumberUtil.
// See metadata_bytes.h for ownership semantics. Default implementation
// returns a non-owning view over a static array; embedders may override.
MetadataBytes GetMetadata();

} // namespace phonenumbers
} // namespace i18n
Expand Down
75 changes: 75 additions & 0 deletions cpp/src/phonenumbers/metadata_bytes.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Copyright (C) 2026 The Libphonenumber Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef I18N_PHONENUMBERS_METADATA_BYTES_H_
#define I18N_PHONENUMBERS_METADATA_BYTES_H_

#include <cstdint>
#include <memory>

namespace i18n {
namespace phonenumbers {

// Owning-or-borrowed view over a serialized PhoneMetadataCollection byte
// buffer returned by the GetMetadata(), GetShortMetadata() and
// GetAlternateFormat() accessors.
//
// The default implementations shipped with libphonenumber return a
// non-owning instance that points at a `static const unsigned char data[]`
// array compiled into the binary, so behaviour and storage are unchanged
// for existing callers.
//
// Embedders that produce the metadata at runtime (for example by
// decompressing it on first use) can return an owning instance constructed
// from a `std::unique_ptr<uint8_t[]>`; the buffer is released when the
// MetadataBytes goes out of scope. The typical call shape
//
// MetadataBytes bytes = GetMetadata();
// collection->ParseFromArray(bytes.data(), bytes.size());
//
// keeps the buffer alive for exactly as long as ParseFromArray() needs it
// and then frees it.
class MetadataBytes {
public:
// Non-owning wrapper around `data` of `size` bytes. `data` must outlive
// this object; pass a pointer to a static array.
MetadataBytes(const void* data, int size) : data_(data), size_(size) {}

// Owning wrapper. The buffer is deleted when this object is destroyed.
MetadataBytes(std::unique_ptr<uint8_t[]> data, int size)
: data_(data.get()), size_(size), owned_(std::move(data)) {}

MetadataBytes(MetadataBytes&&) noexcept = default;
MetadataBytes& operator=(MetadataBytes&&) noexcept = default;

MetadataBytes(const MetadataBytes&) = delete;
MetadataBytes& operator=(const MetadataBytes&) = delete;

~MetadataBytes() = default;

const void* data() const { return data_; }
int size() const { return size_; }

private:
const void* data_;
int size_;
std::unique_ptr<uint8_t[]> owned_;
};

} // namespace phonenumbers
} // namespace i18n

#endif // I18N_PHONENUMBERS_METADATA_BYTES_H_
4 changes: 2 additions & 2 deletions cpp/src/phonenumbers/phonenumbermatcher.cc
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,8 @@ bool AllNumberGroupsRemainGrouped(

bool LoadAlternateFormats(PhoneMetadataCollection* alternate_formats) {
#if defined(I18N_PHONENUMBERS_USE_ALTERNATE_FORMATS)
if (!alternate_formats->ParseFromArray(alternate_format_get(),
alternate_format_size())) {
MetadataBytes bytes = GetAlternateFormat();
if (!alternate_formats->ParseFromArray(bytes.data(), bytes.size())) {
LOG(ERROR) << "Could not parse binary data.";
return false;
}
Expand Down
3 changes: 2 additions & 1 deletion cpp/src/phonenumbers/phonenumberutil.cc
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,8 @@ const char kPossibleCharsAfterExtLabel[] =
const char kOptionalExtSuffix[] = "#?";

bool LoadCompiledInMetadata(PhoneMetadataCollection* metadata) {
if (!metadata->ParseFromArray(metadata_get(), metadata_size())) {
MetadataBytes bytes = GetMetadata();
if (!metadata->ParseFromArray(bytes.data(), bytes.size())) {
LOG(ERROR) << "Could not parse binary data.";
return false;
}
Expand Down
8 changes: 2 additions & 6 deletions cpp/src/phonenumbers/short_metadata.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4122,12 +4122,8 @@ static const unsigned char data[] = {
};
} // namespace

int short_metadata_size() {
return sizeof(data) / sizeof(data[0]);
}

const void* short_metadata_get() {
return data;
MetadataBytes GetShortMetadata() {
return MetadataBytes(data, sizeof(data) / sizeof(data[0]));
}

} // namespace phonenumbers
Expand Down
7 changes: 5 additions & 2 deletions cpp/src/phonenumbers/short_metadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,14 @@
#ifndef I18N_PHONENUMBERS_SHORT_METADATA_H_
#define I18N_PHONENUMBERS_SHORT_METADATA_H_

#include "phonenumbers/metadata_bytes.h"

namespace i18n {
namespace phonenumbers {

int short_metadata_size();
const void* short_metadata_get();
// Returns the serialized short-number PhoneMetadataCollection used by
// ShortNumberInfo. See metadata_bytes.h for ownership semantics.
MetadataBytes GetShortMetadata();

} // namespace phonenumbers
} // namespace i18n
Expand Down
3 changes: 2 additions & 1 deletion cpp/src/phonenumbers/shortnumberinfo.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ using std::map;
using std::string;

bool LoadCompiledInMetadata(PhoneMetadataCollection* metadata) {
if (!metadata->ParseFromArray(short_metadata_get(), short_metadata_size())) {
MetadataBytes bytes = GetShortMetadata();
if (!metadata->ParseFromArray(bytes.data(), bytes.size())) {
LOG(ERROR) << "Could not parse binary data.";
return false;
}
Expand Down
8 changes: 2 additions & 6 deletions cpp/src/phonenumbers/test_metadata.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1044,12 +1044,8 @@ static const unsigned char data[] = {
};
} // namespace

int metadata_size() {
return sizeof(data) / sizeof(data[0]);
}

const void* metadata_get() {
return data;
MetadataBytes GetMetadata() {
return MetadataBytes(data, sizeof(data) / sizeof(data[0]));
}

} // namespace phonenumbers
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,20 +37,27 @@ public final class CppMetadataGenerator {
*/
public enum Type {
/** The basic phone number metadata (expected to be written to metadata.[h/cc]). */
METADATA("metadata", 2011),
METADATA("metadata", "GetMetadata", 2011),
/** The alternate format metadata (expected to be written to alternate_format.[h/cc]). */
ALTERNATE_FORMAT("alternate_format", 2012),
ALTERNATE_FORMAT("alternate_format", "GetAlternateFormat", 2012),
/** Metadata for short numbers (expected to be written to short_metadata.[h/cc]). */
SHORT_NUMBERS("short_metadata", 2013);
SHORT_NUMBERS("short_metadata", "GetShortMetadata", 2013);

private final String typeName;
private final String accessorName;
private final int copyrightYear;

private Type(String typeName, int copyrightYear) {
private Type(String typeName, String accessorName, int copyrightYear) {
this.typeName = typeName;
this.accessorName = accessorName;
this.copyrightYear = copyrightYear;
}

/** Returns the name of the C++ accessor function for this metadata type. */
public String getAccessorName() {
return accessorName;
}

/** Returns the year in which this metadata type was first introduced. */
public int getCopyrightYear() {
return copyrightYear;
Expand Down Expand Up @@ -114,10 +121,11 @@ public void outputHeaderFile(Writer out) throws IOException {
pw.println("#ifndef " + guardName);
pw.println("#define " + guardName);
pw.println();
pw.println("#include \"phonenumbers/metadata_bytes.h\"");
pw.println();
emitNamespaceStart(pw);
pw.println();
pw.println("int " + type + "_size();");
pw.println("const void* " + type + "_get();");
pw.println("MetadataBytes " + type.getAccessorName() + "();");
pw.println();
emitNamespaceEnd(pw);
pw.println();
Expand All @@ -144,12 +152,8 @@ public void outputSourceFile(Writer out) throws IOException {
pw.println("};");
pw.println("} // namespace");
pw.println();
pw.println("int " + type + "_size() {");
pw.println(" return sizeof(data) / sizeof(data[0]);");
pw.println("}");
pw.println();
pw.println("const void* " + type + "_get() {");
pw.println(" return data;");
pw.println("MetadataBytes " + type.getAccessorName() + "() {");
pw.println(" return MetadataBytes(data, sizeof(data) / sizeof(data[0]));");
pw.println("}");
pw.println();
emitNamespaceEnd(pw);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,9 @@ public void generateMetadata() {
command.start();
// Sanity check the captured data (asserting implicitly that the mocked methods were called).
String headerString = command.capturedHeaderFile();
assertTrue(headerString.contains("const void* metadata_get()"));
assertTrue(headerString.contains("int metadata_size()"));
assertTrue(headerString.contains("MetadataBytes GetMetadata()"));
String sourceString = command.capturedSourceFile();
assertTrue(sourceString.contains("const void* metadata_get()"));
assertTrue(sourceString.contains("int metadata_size()"));
assertTrue(sourceString.contains("MetadataBytes GetMetadata()"));
assertTrue(sourceString.contains(CPP_TEST_DATA));
}

Expand All @@ -107,11 +105,9 @@ public void generateLiteMetadata() {
command.start();
// Sanity check the captured data (asserting implicitly that the mocked methods were called).
String headerString = command.capturedHeaderFile();
assertTrue(headerString.contains("const void* metadata_get()"));
assertTrue(headerString.contains("int metadata_size()"));
assertTrue(headerString.contains("MetadataBytes GetMetadata()"));
String sourceString = command.capturedSourceFile();
assertTrue(sourceString.contains("const void* metadata_get()"));
assertTrue(sourceString.contains("int metadata_size()"));
assertTrue(sourceString.contains("MetadataBytes GetMetadata()"));
assertTrue(sourceString.contains(CPP_TEST_DATA));
}

Expand All @@ -126,11 +122,9 @@ public void generateAlternateFormat() {
command.start();
// Sanity check the captured data (asserting implicitly that the mocked methods were called).
String headerString = command.capturedHeaderFile();
assertTrue(headerString.contains("const void* alternate_format_get()"));
assertTrue(headerString.contains("int alternate_format_size()"));
assertTrue(headerString.contains("MetadataBytes GetAlternateFormat()"));
String sourceString = command.capturedSourceFile();
assertTrue(sourceString.contains("const void* alternate_format_get()"));
assertTrue(sourceString.contains("int alternate_format_size()"));
assertTrue(sourceString.contains("MetadataBytes GetAlternateFormat()"));
assertTrue(sourceString.contains(CPP_TEST_DATA));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ public void outputHeaderFile() throws IOException {
assertTrue(consumeUntil("#define I18N_PHONENUMBERS_METADATA_H_", lines));
assertTrue(consumeUntil("namespace i18n {", lines));
assertTrue(consumeUntil("namespace phonenumbers {", lines));
assertTrue(consumeUntil("int metadata_size();", lines));
assertTrue(consumeUntil("const void* metadata_get();", lines));
assertTrue(consumeUntil("#include \"phonenumbers/metadata_bytes.h\"", lines));
assertTrue(consumeUntil("MetadataBytes GetMetadata();", lines));
assertTrue(consumeUntil("#endif // I18N_PHONENUMBERS_METADATA_H_", lines));
}

Expand All @@ -90,8 +90,7 @@ public void outputSourceFile() throws IOException {
assertTrue(consumeUntil("namespace {", lines));
assertTrue(consumeUntil("static const unsigned char data[] = {", lines));
assertTrue(consumeUntil(" 0xCA, 0xFE, 0xBA, 0xBE", lines));
assertTrue(consumeUntil("int alternate_format_size() {", lines));
assertTrue(consumeUntil("const void* alternate_format_get() {", lines));
assertTrue(consumeUntil("MetadataBytes GetAlternateFormat() {", lines));
}

/** Converts a string containing newlines into a list of lines. */
Expand Down