1 /* bzflag
2  * Copyright (c) 1993-2021 Tim Riker
3  *
4  * This package is free software;  you can redistribute it and/or
5  * modify it under the terms of the license found in the file
6  * named COPYING that should have accompanied this file.
7  *
8  * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
9  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
10  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
11  */
12 
13 /* interface header */
14 #include "TextChunkManager.h"
15 
16 /* system implementation headers */
17 #include <fstream>
18 
19 /* common headers */
20 #include "TextUtils.h"
21 
22 /******************************************************************************/
23 
TextChunk()24 TextChunk::TextChunk() :
25     fileName(""),
26     maxLines(-1),
27     maxLineLength(-1)
28 {
29     // for the <map>[] operator
30 }
31 
32 
TextChunk(const std::string & _fileName,int _maxLines,int _maxLineLength)33 TextChunk::TextChunk(const std::string& _fileName, int _maxLines, int _maxLineLength)
34 {
35     fileName = _fileName;
36     maxLines = _maxLines;
37     maxLineLength = _maxLineLength < 0 ? (int)std::string::npos : _maxLineLength;
38     theVector = parse();
39     return;
40 }
41 
42 
parse()43 StringVector TextChunk::parse()
44 {
45     StringVector strings;
46     std::ifstream in(fileName.c_str());
47 
48     if (!in)
49     {
50         strings.push_back(TextUtils::format("WARNING: unable to open %s", fileName.c_str()));
51         return strings;
52     }
53 
54     // read at most maxLines lines
55     int long_lines_encountered = 0;
56     int linecount = 0;
57     std::string line;
58 
59     while (getline(in, line))
60     {
61 
62         // read at most maxLines lines (-1 = no limit)
63         if (maxLines > 0 && linecount == maxLines)
64         {
65             strings.push_back(TextUtils::format("WARNING: %s has more than %d lines, truncated.", fileName.c_str(), maxLines));
66             break;
67         }
68 
69         // truncate long lines
70         if ((int)line.size() > maxLineLength)
71         {
72             line.erase(maxLineLength);
73             long_lines_encountered++;
74         }
75 
76         strings.push_back(line);
77         linecount++;
78     }
79 
80     // warn about long lines
81     if (long_lines_encountered)
82         strings.push_back(TextUtils::format("WARNING: truncated %d long line%s from %s (limit of %d characters)",
83                                             long_lines_encountered, long_lines_encountered == 1? "" : "s", fileName.c_str(), maxLineLength));
84 
85     return strings;
86 }
87 
88 
reload()89 bool TextChunk::reload()
90 {
91     StringVector newVec = parse();
92     if (newVec.size() > 0)
93         theVector = newVec;
94     return (theVector.size() > 0);
95 }
96 
97 
size() const98 size_t TextChunk::size() const
99 {
100     return theVector.size();
101 }
102 
103 
getVector() const104 const StringVector& TextChunk::getVector() const
105 {
106     return theVector;
107 }
108 
109 
110 /******************************************************************************/
111 
parseFile(const std::string & fileName,const std::string & chunkName,const int maxLines,const int maxLineLength)112 bool TextChunkManager::parseFile(const std::string &fileName,
113                                  const std::string &chunkName,
114                                  const int maxLines,
115                                  const int maxLineLength)
116 {
117     TextChunk textChunk(fileName, maxLines, maxLineLength);
118 
119     if (textChunk.size() <= 0)
120         return false;
121 
122     // add a new chunk name if it isn't already listed
123     if (theChunks.find(chunkName) == theChunks.end())
124         chunkNames.push_back(chunkName);
125 
126     // add or replace the chunk
127     theChunks[chunkName] = textChunk;
128 
129     return true;
130 }
131 
132 
getTextChunk(const std::string & chunkName) const133 const StringVector* TextChunkManager::getTextChunk(const std::string &chunkName) const
134 {
135     TextChunkMap::const_iterator it;
136     it = theChunks.find(chunkName);
137     if (it != theChunks.end())
138         return &it->second.getVector();
139     else
140         return NULL;
141 }
142 
143 
getChunkNames() const144 const StringVector& TextChunkManager::getChunkNames() const
145 {
146     return chunkNames;
147 }
148 
149 
reload()150 void TextChunkManager::reload()
151 {
152     TextChunkMap::iterator it;
153     for (it = theChunks.begin(); it != theChunks.end(); ++it)
154         it->second.reload();
155     return;
156 }
157 
158 
159 /******************************************************************************/
160 
161 
162 // Local Variables: ***
163 // mode: C++ ***
164 // tab-width: 4 ***
165 // c-basic-offset: 4 ***
166 // indent-tabs-mode: nil ***
167 // End: ***
168 // ex: shiftwidth=4 tabstop=4
169