blob: b564d3eb06430eb9fe30dd73703f86fd8817c204 [file] [log] [blame]
// Copyright 2014 Google Inc. All Rights Reserved.
//
// 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.
#include <assert.h>
#include <stdio.h>
#include <fstream>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include "cld2_dynamic_data.h"
#include "cld2_dynamic_data_extractor.h"
#include "cld2_dynamic_data_loader.h"
#include "integral_types.h"
#include "cld2tablesummary.h"
#include "utf8statetable.h"
#include "scoreonescriptspan.h"
// We need these in order to set up a real data object to pass around.
namespace CLD2 {
extern const UTF8PropObj cld_generated_CjkUni_obj;
extern const CLD2TableSummary kCjkCompat_obj;
extern const CLD2TableSummary kCjkDeltaBi_obj;
extern const CLD2TableSummary kDistinctBiTable_obj;
extern const CLD2TableSummary kQuad_obj;
extern const CLD2TableSummary kQuad_obj2;
extern const CLD2TableSummary kDeltaOcta_obj;
extern const CLD2TableSummary kDistinctOcta_obj;
extern const short kAvgDeltaOctaScore[];
extern const uint32 kAvgDeltaOctaScoreSize;
extern const uint32 kCompatTableIndSize;
extern const uint32 kCjkDeltaBiIndSize;
extern const uint32 kDistinctBiTableIndSize;
extern const uint32 kQuadChromeIndSize;
extern const uint32 kQuadChrome2IndSize;
extern const uint32 kDeltaOctaIndSize;
extern const uint32 kDistinctOctaIndSize;
}
int main(int argc, char** argv) {
if (!CLD2DynamicData::isLittleEndian()) {
fprintf(stderr, "System is big-endian: currently not supported.\n");
return -1;
}
if (!CLD2DynamicData::coreAssumptionsOk()) {
fprintf(stderr, "Core assumptions violated, unsafe to continue.\n");
return -2;
}
// Get command-line flags
int flags = 0;
bool get_vector = false;
char* fileName = NULL;
const char* USAGE = "\
CLD2 Dynamic Data Tool:\n\
Dump, verify or print summaries of scoring tables for CLD2.\n\
\n\
The files output by this tool are suitable for all little-endian platforms,\n\
and should work on both 32- and 64-bit platforms.\n\
\n\
IMPORTANT: The files output by this tool WILL NOT work on big-endian platforms.\n\
\n\
Usage:\n\
--dump [FILE] Dump the scoring tables that this tool was linked against\n\
to the specified file. The tables are automatically verified\n\
after writing, just as if the tool was run again with\n\
'--verify'.\n\
--verify [FILE] Verify that a given file precisely matches the scoring\n\
tables that this tool was linked against. This can be used\n\
to verify that a file is compatible.\n\
--head [FILE] Print headers from the specified file to stdout.\n\
--verbose Be verbose.\n\
";
int mode = 0; //1=dump, 2=verify, 3=head
for (int i = 1; i < argc; ++i) {
if (strcmp(argv[i], "--verbose") == 0) {
CLD2DynamicDataExtractor::setDebug(1);
CLD2DynamicData::setDebug(1);
}
else if (strcmp(argv[i], "--dump") == 0
|| strcmp(argv[i], "--verify") == 0
|| strcmp(argv[i], "--head") == 0) {
// set mode flag properly
if (strcmp(argv[i], "--dump") == 0) mode=1;
else if (strcmp(argv[i], "--verify") == 0) mode=2;
else mode=3;
if (i < argc - 1) {
fileName = argv[++i];
} else {
fprintf(stderr, "Missing file name argument\n\n");
fprintf(stderr, "%s", USAGE);
return -1;
}
} else if (strcmp(argv[i], "--help") == 0) {
fprintf(stdout, "%s", USAGE);
return 0;
} else {
fprintf(stderr, "Unsupported option: %s\n\n", argv[i]);
fprintf(stderr, "%s", USAGE);
return -1;
}
}
if (mode == 0) {
fprintf(stderr, "%s", USAGE);
return -1;
}
CLD2::ScoringTables realData = {
&CLD2::cld_generated_CjkUni_obj,
&CLD2::kCjkCompat_obj,
&CLD2::kCjkDeltaBi_obj,
&CLD2::kDistinctBiTable_obj,
&CLD2::kQuad_obj,
&CLD2::kQuad_obj2,
&CLD2::kDeltaOcta_obj,
&CLD2::kDistinctOcta_obj,
CLD2::kAvgDeltaOctaScore,
};
const CLD2::uint32 indirectTableSizes[7] = {
CLD2::kCompatTableIndSize,
CLD2::kCjkDeltaBiIndSize,
CLD2::kDistinctBiTableIndSize,
CLD2::kQuadChromeIndSize,
CLD2::kQuadChrome2IndSize,
CLD2::kDeltaOctaIndSize,
CLD2::kDistinctOctaIndSize
};
const CLD2DynamicData::Supplement supplement = {
CLD2::kAvgDeltaOctaScoreSize,
indirectTableSizes
};
if (mode == 1) { // dump
CLD2DynamicDataExtractor::writeDataFile(
static_cast<const CLD2::ScoringTables*>(&realData),
&supplement,
fileName);
} else if (mode == 3) { // head
CLD2DynamicData::FileHeader* header = CLD2DynamicDataLoader::loadHeaderFromFile(fileName);
if (header == NULL) {
fprintf(stderr, "Cannot read header from file: %s\n", fileName);
return -1;
}
CLD2DynamicData::dumpHeader(header);
delete[] header->tableHeaders;
delete header;
}
if (mode == 1 || mode == 2) { // dump || verify (so perform verification)
void* mmapAddress = NULL;
uint32_t mmapLength = 0;
CLD2::ScoringTables* loadedData = CLD2DynamicDataLoader::loadDataFile(fileName, &mmapAddress, &mmapLength);
if (loadedData == NULL) {
fprintf(stderr, "Failed to read data file: %s\n", fileName);
return -1;
}
bool result = CLD2DynamicData::verify(
static_cast<const CLD2::ScoringTables*>(&realData),
&supplement,
static_cast<const CLD2::ScoringTables*>(loadedData));
CLD2DynamicDataLoader::unloadDataFile(&loadedData, &mmapAddress, &mmapLength);
if (loadedData != NULL || mmapAddress != NULL || mmapLength != 0) {
fprintf(stderr, "Warning: failed to clean up memory for ScoringTables.\n");
}
if (!result) {
fprintf(stderr, "Verification failed!\n");
return -1;
}
}
}