blob: 0fab98a1fc87409ec140c1b64a035c9f43340ce8 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001#include "res_check.h"
2#include "localize.h"
3#include "file_utils.h"
4#include "ValuesFile.h"
5
6#include <stdio.h>
7
8static int check_file(const ValuesFile* file);
9static int check_value(const SourcePos& pos, const XMLNode* value);
10static int scan_for_unguarded_format(const SourcePos& pos, const XMLNode* value, int depth = 0);
11
12int
13do_rescheck(const vector<string>& files)
14{
15 int err;
16
17 Configuration english;
18 english.locale = "en_US";
19
20 for (size_t i=0; i<files.size(); i++) {
21 const string filename = files[i];
22 ValuesFile* valuesFile = get_local_values_file(filename, english, CURRENT_VERSION,
23 "0", true);
24 if (valuesFile != NULL) {
25 err |= check_file(valuesFile);
26 delete valuesFile;
27 } else {
28 err |= 1;
29 }
30 }
31
32 return err;
33}
34
35static int
36check_file(const ValuesFile* file)
37{
38 int err = 0;
39 set<StringResource> strings = file->GetStrings();
40 for (set<StringResource>::iterator it=strings.begin(); it!=strings.end(); it++) {
41 XMLNode* value = it->value;
42 if (value != NULL) {
43 err |= check_value(it->pos, value);
44 }
45 }
46 return err;
47}
48
49static bool
50contains_percent(const string& str)
51{
52 const size_t len = str.length();
53 for (size_t i=0; i<len; i++) {
54 char c = str[i];
55 if (c == '%') {
56 return true;
57 }
58 }
59 return false;
60}
61
62static int
63check_value(const SourcePos& pos, const XMLNode* value)
64{
65 int err = 0;
66 err |= scan_for_unguarded_format(pos, value);
67 return err;
68}
69
70static bool
71is_xliff_block(const string& ns, const string& name)
72{
73 if (ns == XLIFF_XMLNS) {
74 return name == "g";
75 } else {
76 return false;
77 }
78}
79
80static int
81scan_for_unguarded_format(const SourcePos& pos, const string& string)
82{
83 bool containsPercent = contains_percent(string);
84 if (containsPercent) {
85 pos.Error("unguarded percent: '%s'\n", string.c_str());
86 }
87 return 0;
88}
89
90static int
91scan_for_unguarded_format(const SourcePos& pos, const XMLNode* value, int depth)
92{
93 if (value->Type() == XMLNode::ELEMENT) {
94 int err = 0;
95 if (depth == 0 || !is_xliff_block(value->Namespace(), value->Name())) {
96 const vector<XMLNode*>& children = value->Children();
97 for (size_t i=0; i<children.size(); i++) {
98 err |= scan_for_unguarded_format(pos, children[i], depth+1);
99 }
100 }
101 return err;
102 } else {
103 return scan_for_unguarded_format(pos, value->Text());
104 }
105}
106