- Refuse to build a dictionary with a non-alphabetical character (except '?')

- Marked many strings for translation, and improved their formatting
This commit is contained in:
Olivier Teulière 2010-01-02 12:44:56 +00:00
parent ae6b40874c
commit 2404d359ca
2 changed files with 60 additions and 38 deletions

View file

@ -26,6 +26,7 @@
#include <iostream>
#include <vector>
#include <map>
#include <boost/format.hpp>
#include <boost/foreach.hpp>
#include <boost/tokenizer.hpp>
#include <boost/unordered_map.hpp>
@ -70,6 +71,9 @@
using namespace std;
// Useful shortcut
#define fmt(a) boost::format(a)
//#define DEBUG_OUTPUT
#define CHECK_RECURSION
@ -78,7 +82,7 @@ unsigned int getFileSize(const string &iFileName)
{
struct stat stat_buf;
if (stat(iFileName.c_str(), &stat_buf) < 0)
throw DicException(_("Cannot stat file ") + iFileName);
throw DicException((fmt(_("Cannot stat file '%1%'")) % iFileName).str());
return (unsigned int)stat_buf.st_size;
}
@ -86,7 +90,7 @@ const wchar_t* load_uncompressed(const string &iFileName, unsigned int &ioDicSiz
{
ifstream file(iFileName.c_str(), ios::in | ios::binary);
if (!file.is_open())
throw DicException("Could not open file " + iFileName);
throw DicException((fmt(_("Could not open file '%1%'")) % iFileName).str());
// Place the buffer in a vector to avoid worrying about memory handling
vector<char> buffer(ioDicSize);
@ -118,7 +122,7 @@ void readLetters(const string &iFileName, DictHeaderInfo &ioHeaderInfo)
{
ifstream in(iFileName.c_str());
if (!in.is_open())
throw DicException("Could not open file " + string(iFileName));
throw DicException((fmt(_("Could not open file '%1%'")) % iFileName).str());
// Use a more friendly type name
typedef boost::tokenizer<boost::char_separator<wchar_t>,
@ -145,8 +149,8 @@ void readLetters(const string &iFileName, DictHeaderInfo &ioHeaderInfo)
if (tokens.size() < 5)
{
ostringstream ss;
ss << "readLetters: Not enough fields in " << iFileName;
ss << " (line " << lineNb << ")";
ss << fmt(_("readLetters: Not enough fields "
"in %1% (line %2%)")) % iFileName % lineNb;
throw DicException(ss.str());
}
@ -166,13 +170,30 @@ void readLetters(const string &iFileName, DictHeaderInfo &ioHeaderInfo)
else
{
ostringstream ss;
ss << "readLetters: Invalid letter at line " << lineNb;
ss << " (only one character allowed)";
ss << fmt(_("readLetters: Invalid letter at line %1% "
"(only one character allowed)")) % lineNb;
throw DicException(ss.str());
}
}
wchar_t upChar = towupper(letter[0]);
// We don't support non-alphabetical characters in the dictionary
// apart from the joker '?'. For more explanations on the issue, see
// on the eliot-dev mailing-list the thread with the following title:
// re: Unable to show menus in Catalan, and some weird char "problem"
// (started on 2009/12/31)
wchar_t chr = letter[0];
if (!iswalpha(chr) && chr != L'?')
{
ostringstream ss;
ss << fmt(_("'%1%' is not a valid letter.")) % convertToMb(letter) << endl;
ss << fmt(_("For technical reasons, Eliot currently only supports "
"alphabetical characters as internal character "
"representation, even if the tile has a display string "
"defined. Please use another character and change your "
"word list accordingly."));
throw DicException(ss.str());
}
wchar_t upChar = towupper(chr);
ioHeaderInfo.letters += upChar;
ioHeaderInfo.points.push_back(_wtoi(tokens[1].c_str()));
@ -189,7 +210,7 @@ void readLetters(const string &iFileName, DictHeaderInfo &ioHeaderInfo)
std::transform(str.begin(), str.end(), str.begin(), towupper);
}
// If the display stirng is identical to the internal char and if
// If the display string is identical to the internal char and if
// there is no other input, no need to save this information, as
// it is already the default.
if (inputs.size() != 1 || inputs[0] != wstring(1, upChar))
@ -244,7 +265,7 @@ void write_node(uint32_t *ioEdges, unsigned int num, ostream &outfile)
}
#ifdef DEBUG_OUTPUT
printf("writing %d edges\n", num);
cout << fmt(_("writing %1% edges")) % num << endl;
for (int i = 0; i < num; i++)
{
outfile.write((char*)(ioEdges + i), sizeof(DicEdge));
@ -354,9 +375,10 @@ unsigned int makenode(const wchar_t *iPrefix, ostream &outfile,
{
// If an invalid character is found, be specific about the problem
ostringstream oss;
oss << "Error on line " << 1 + ioHeaderInfo.nwords
<< ", col " << global_endstring - global_stringbuf
<< ": " << e.what() << endl;
oss << fmt(_("Error on line %1%, col %2%: %3%"))
% (1 + ioHeaderInfo.nwords)
% (global_endstring - global_stringbuf)
% e.what() << endl;
throw DicException(oss.str());
}
edges.push_back(newEdge);
@ -553,7 +575,7 @@ int main(int argc, char* argv[])
ofstream outfile(outFileName.c_str(), ios::out | ios::binary | ios::trunc);
if (!outfile.is_open())
{
cerr << _("Cannot open output file ") << outFileName << endl;
cerr << fmt(_("Cannot open output file '%1%'")) % outFileName << endl;
exit(1);
}
@ -599,13 +621,13 @@ int main(int argc, char* argv[])
printf(_(" Load time: %.3f s\n"), 1.0 * (endLoadTime - startLoadTime) / CLOCKS_PER_SEC);
printf(_(" Compression time: %.3f s\n"), 1.0 * (endBuildTime - startBuildTime) / CLOCKS_PER_SEC);
#ifdef CHECK_RECURSION
printf(_(" Maximum recursion level reached: %d\n"), max_rec);
cout << fmt(_(" Maximum recursion level reached: %1%")) % max_rec << endl;
#endif
return 0;
}
catch (std::exception &e)
{
cerr << e.what() << endl;
cerr << fmt(_("Exception caught: %1%")) % e.what() << endl;
return 1;
}
}

View file

@ -193,11 +193,10 @@ Header::Header(const DictHeaderInfo &iInfo)
// Sanity checks
if (iInfo.letters.size() > _MAX_LETTERS_NB_)
{
ostringstream ss;
ss << _MAX_LETTERS_NB_;
throw DicException("Header::Header: Too many different letters for "
"the current format; only " + ss.str() +
" are supported");
format fmt(_("Header::Header: Too many different letters for "
"the current format; only %1% are supported"));
fmt % _MAX_LETTERS_NB_;
throw DicException(fmt.str());
}
if (iInfo.points.size() != iInfo.letters.size())
{
@ -291,9 +290,9 @@ wchar_t Header::getCharFromCode(unsigned int iCode) const
// Safety check
if (iCode == 0 || iCode > m_letters.size())
{
ostringstream oss;
oss << iCode;
throw DicException("Header::getCharFromCode: no letter for code " + oss.str());
format fmt(_("Header::getCharFromCode: No letter for code '%1%'"));
fmt % iCode;
throw DicException(fmt.str());
}
return m_letters[iCode - 1];
}
@ -307,8 +306,9 @@ unsigned int Header::getCodeFromChar(wchar_t iChar) const
{
char s[5];
sprintf(s, "%d", iChar);
throw DicException("Header::getCodeFromChar: No code for letter '" +
convertToMb(iChar) + "' (val=" + string(s) + ")");
format fmt(_("Header::getCodeFromChar: No code for letter '%1%' (val=%2%)"));
fmt % convertToMb(iChar) % s;
throw DicException(fmt.str());
}
return pair->second;
}
@ -620,22 +620,22 @@ wstring Header::writeDisplayAndInput() const
void Header::print() const
{
#define fmt(x) format(_(x))
cout << fmt("Dictionary name: %1%") % convertToMb(m_dicName) << endl;
#define fmt(x) boost::format(x)
cout << fmt(_("Dictionary name: %1%")) % convertToMb(m_dicName) << endl;
char buf[150];
strftime(buf, sizeof(buf), "%c", gmtime(&m_compressDate));
cout << fmt("Compressed on: %1%") % buf << endl;
cout << fmt("Compressed using a binary compiled by: %1%") % convertToMb(m_userHost) << endl;
cout << fmt("Dictionary type: %1%") % (m_type == kDAWG ? "DAWG" : "GADDAG") << endl;
cout << fmt("Letters: %1%") % convertToMb(m_letters) << endl;
cout << fmt("Number of letters: %1%") % m_letters.size() << endl;
cout << fmt("Number of words: %1%") % m_nbWords << endl;
cout << fmt(_("Compressed on: %1%")) % buf << endl;
cout << fmt(_("Compressed using a binary compiled by: %1%")) % convertToMb(m_userHost) << endl;
cout << fmt(_("Dictionary type: %1%")) % (m_type == kDAWG ? "DAWG" : "GADDAG") << endl;
cout << fmt(_("Letters: %1%")) % convertToMb(m_letters) << endl;
cout << fmt(_("Number of letters: %1%")) % m_letters.size() << endl;
cout << fmt(_("Number of words: %1%")) % m_nbWords << endl;
long unsigned int size = sizeof(Dict_header_old) +
sizeof(Dict_header_ext) + sizeof(Dict_header_ext_2);
cout << fmt("Header size: %1% bytes") % size << endl;
cout << fmt("Root: %1% (edge)") % m_root << endl;
cout << fmt("Nodes: %1% used + %2% saved") % m_nodesUsed % m_nodesSaved << endl;
cout << fmt("Edges: %1% used + %2% saved") % m_edgesUsed % m_edgesSaved << endl;
cout << fmt(_("Header size: %1% bytes")) % size << endl;
cout << fmt(_("Root: %1% (edge)")) % m_root << endl;
cout << fmt(_("Nodes: %1% used + %2% saved")) % m_nodesUsed % m_nodesSaved << endl;
cout << fmt(_("Edges: %1% used + %2% saved")) % m_edgesUsed % m_edgesSaved << endl;
#undef fmt
cout << "====================================================================" << endl;
cout << format("%1% | %2% | %3% | %4% | %5% | %6% | %7%")