NCBI C++ ToolKit
citation_base.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1  /*$Id: citation_base.cpp 66776 2015-03-24 16:16:20Z gotvyans $
2  * ===========================================================================
3  *
4  * PUBLIC DOMAIN NOTICE
5  * National Center for Biotechnology Information
6  *
7  * This software/database is a "United States Government Work" under the
8  * terms of the United States Copyright Act. It was written as part of
9  * the author's official duties as a United States Government employee and
10  * thus cannot be copyrighted. This software/database is freely available
11  * to the public for use. The National Library of Medicine and the U.S.
12  * Government have not placed any restriction on its use or reproduction.
13  *
14  * Although all reasonable efforts have been taken to ensure the accuracy
15  * and reliability of the software and data, the NLM and the U.S.
16  * Government do not and cannot warrant the performance or results that
17  * may be obtained by using this software or data. The NLM and the U.S.
18  * Government disclaim all warranties, express or implied, including
19  * warranties of performance, merchantability or fitness for any particular
20  * purpose.
21  *
22  * Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Author: Clifford Clausen, Aleksey Grichenko
27  * (moved from CPub class)
28  *
29  * File Description:
30  * utility functions for GetLabel()
31  *
32  */
33 
34 #include <ncbi_pch.hpp>
36 
37 #include <objects/general/Date.hpp>
41 #include <objects/biblio/Title.hpp>
43 
44 #include <typeinfo>
45 
47 BEGIN_objects_SCOPE
48 
50  ELabelVersion version) const
51 {
52  _ASSERT(label != NULL);
53  if (version < eLabel_MinVersion || version > eLabel_MaxVersion) {
54  ERR_POST(Warning << "Unsupported citation label version " << version
55  << "; substituting default (" << eLabel_DefaultVersion << ')');
57  }
58  switch (version) {
59  case eLabel_V1: return GetLabelV1(label, flags);
60  case eLabel_V2: return GetLabelV2(label, flags);
61  default: _TROUBLE;
62  }
63  return false;
64 }
65 
66 
67 string ICitationBase::FixPages(const string& raw_orig_pages)
68 {
69  if (raw_orig_pages.empty()) {
70  return kEmptyStr;
71  }
72 
73  SIZE_TYPE hyphen_pos = NPOS, lhs_digit_pos = NPOS, lhs_letter_pos = NPOS,
74  digit_pos = NPOS, letter_pos = NPOS;
75 
76  CTempString orig_pages = NStr::TruncateSpaces_Unsafe(raw_orig_pages);
77  for (SIZE_TYPE pos = 0; pos < orig_pages.size(); ++pos) {
78  char c = orig_pages[pos];
79  if (c >= '0' && c <= '9') {
80  if (digit_pos == NPOS) {
81  digit_pos = pos;
82  } else if (letter_pos > digit_pos && letter_pos != NPOS) {
83  return orig_pages; // invalid -- letters on either side
84  }
85  } else if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) {
86  if (letter_pos == NPOS) {
87  letter_pos = pos;
88  } else if (digit_pos > letter_pos && digit_pos != NPOS) {
89  return orig_pages; // invalid -- digits on either side
90  }
91  } else if (c == '-' && digit_pos != NPOS && hyphen_pos == NPOS) {
92  hyphen_pos = pos;
93  lhs_digit_pos = digit_pos;
94  lhs_letter_pos = letter_pos;
95  digit_pos = letter_pos = NPOS;
96  } else {
97  return orig_pages;
98  }
99  }
100 
101  CTempString lhs(orig_pages, 0, hyphen_pos);
102  if (lhs == orig_pages.substr(hyphen_pos + 1)) {
103  return lhs;
104  }
105 
106  if (lhs_letter_pos > 0 && lhs_letter_pos != NPOS) {
107  _ASSERT(lhs_digit_pos == 0);
108  // Complex LHS, digits first; canonicalize 12a-c case (with a
109  // single letter on each side), otherwise leave alone apart
110  // from collapsing trivial (single-page) ranges.
111  if (lhs_letter_pos == hyphen_pos - 1
112  && letter_pos == hyphen_pos + 1
113  && orig_pages.size() == letter_pos + 1) {
114  int diff = orig_pages[letter_pos] - orig_pages[lhs_letter_pos];
115  if (diff == 0) {
116  return lhs;
117  } else if (diff > 0) {
118  string result(orig_pages, 0, letter_pos);
119  result.append(orig_pages, 0, lhs_letter_pos);
120  result += orig_pages[letter_pos];
121  return result;
122  }
123  }
124  } else if (letter_pos == NPOS && digit_pos != NPOS) {
125  // At this point, any letters on the LHS are known to precede
126  // its digits; as such, if the RHS consists solely of digits
127  // (checked just now), it may be subject to canonicalization.
128  // (Should this reject page numbers starting with multiple letters?)
129  CTempString lhs_digits(lhs, lhs_digit_pos), rhs(orig_pages, digit_pos);
130  if (NStr::EndsWith(lhs, rhs)) {
131  return lhs;
132  } else if (lhs_digits.size() >= rhs.size()) {
133  SIZE_TYPE lhs_tail_pos = lhs.size() - rhs.size();
134  if (lhs.substr(lhs_tail_pos) < rhs) {
135  string result(orig_pages, 0, hyphen_pos + 1);
136  result.append(lhs, 0, lhs_tail_pos);
137  result.append(rhs);
138  return result;
139  }
140  } else if (lhs_letter_pos != NPOS
141  && rhs.size() > hyphen_pos - lhs_digit_pos) {
142  // Handle A9-10 and the like.
143  _ASSERT(lhs_letter_pos == 0);
144  string result(orig_pages, 0, hyphen_pos + 1);
145  result.append(lhs.substr(0, lhs_digit_pos));
146  result.append(rhs);
147  return result;
148  }
149  }
150 
151  return orig_pages;
152 }
153 
154 
156 {
157  if (date.IsStd()) {
158  string year;
159  date.GetDate(&year, "(%4Y)");
160  return year;
161  } else if (date.IsStr() && HasText(date.GetStr())
162  && date.GetStr() != "?") {
163  return '(' + date.GetStr().substr(0, 4) + ')';
164  } else {
165  return kEmptyStr;
166  }
167 }
168 
169 
171 {
172  _ASSERT(label != NULL);
173 
174  const string* issue = ip.CanGetIssue() ? &ip.GetIssue() : NULL;
175  const string* part_sup = ip.CanGetPart_sup() ? &ip.GetPart_sup() : NULL;
176  const string* part_supi = ip.CanGetPart_supi() ? &ip.GetPart_supi() : NULL;
177 
178  if (HasText(part_sup)) {
180  *label += *part_sup;
181  }
182  if (HasText(issue) || HasText(part_supi)) {
184  *label += '(';
185  if (HasText(issue)) {
186  *label += *issue;
187  }
188  if (HasText(part_supi)) {
189  *label += ' ' + *part_supi;
190  }
191  *label += ')';
192  }
193 }
194 
195 
197  bool unique,
198  const CAuth_list* authors,
199  const CImprint* imprint,
200  const CTitle* title,
201  const CCit_book* book,
202  const CCit_jour* /* journal */,
203  const string* title1,
204  const string* title2,
205  const string* titleunique,
206  const string* date,
207  const string* volume,
208  const string* issue,
209  const string* pages,
210  bool unpublished)
211 {
212  const string* part_sup = 0;
213  const string* part_supi = 0;
214  string subst_date;
215  if (imprint) {
216  if ( !date ) {
217  imprint->GetDate().GetDate(&subst_date);
218  date = &subst_date;
219  }
220  volume = !volume && imprint->IsSetVolume() ?
221  &imprint->GetVolume() : volume;
222  issue = !issue && imprint->IsSetIssue() ? &imprint->GetIssue() : issue;
223  pages = !pages && imprint->IsSetPages() ? &imprint->GetPages() : pages;
224  part_sup = imprint->IsSetPart_sup() ? &imprint->GetPart_sup() : 0;
225  part_supi = imprint->IsSetPart_supi() ? &imprint->GetPart_supi() : 0;
226  }
227 
228  if (authors) {
229  authors->GetLabel(label, 0, eLabel_V1);
230  }
231 
232  if (date) {
234  *label += '(' + *date + ") ";
235  }
236 
237  if (title && !titleunique) {
238  try {
239  titleunique = &title->GetTitle();
240  } catch (exception&) {}
241  }
242 
243  if (title && !title2) {
244  try {
245  title2 = &title->GetTitle();
246  } catch (exception&) {}
247  }
248 
249  if (title2) {
250  if (book) {
251  *label += "(in) " + *title2 + " ";
252  } else if (title1) {
253  *label += *title1 + *title2 + " ";
254  }
255  else {
256  *label += *title2 + " ";
257  }
258  }
259 
260  if (volume) {
261  if (part_sup) {
262  *label += *volume + *part_sup + ":";
263  }
264  else {
265  *label += *volume + ":";
266  }
267  }
268 
269  if (issue) {
270  if (part_supi) {
271  *label += "(" + *issue + *part_supi + ")";
272  }
273  else {
274  *label += "(" + *issue + ")";
275  }
276  }
277 
278  if (pages) {
279  *label += *pages;
280  }
281 
282  if (unpublished) {
283  *label += "Unpublished";
284  }
285 
286  // If unique parameter true, then add unique tag to end of label
287  // constructed from the first character of each whitespace separated
288  // word in titleunique
289  if (unique) {
290  //string tag;
291  // NB: add '|' even if tag is empty to maintain backward compatibility.
292  *label += '|';
293  if (titleunique && !titleunique->empty()) {
294 #if 0
295  CNcbiIstrstream is(titleunique->c_str(), titleunique->size());
296  string word;
297  int cnt = 0;
298  while ( (is >> word) && (cnt++ < 40) ) {
299  *label += word[0];
300  }
301 #else
302  size_t pos;
303  CTempString temp = *titleunique;
304  CTempString space(" \t\r\n");
305  while ( (pos = temp.find_first_not_of(space)) != CTempString::npos)
306  {
307  *label += temp[pos];
308  temp.assign(temp, pos, temp.size() - pos);
309  pos = temp.find_first_of(space);
310  if (pos != CTempString::npos)
311  temp.assign(temp, pos, temp.size() - pos);
312  else
313  break;
314  }
315 #endif
316  }
317  }
318 
319  return true;
320 }
321 
322 
323 END_objects_SCOPE
User-defined methods of the data storage class.
"Mix-in" interfaces to implement GetLabel for CCit_* et al.
@Auth_list.hpp User-defined methods of the data storage class.
Definition: Auth_list.hpp:57
Definition: Date.hpp:53
void GetDate(string *label, bool year_only=false) const
Append a standardized string representation of the date to the label.
Definition: Date.hpp:149
CImprint –.
Definition: Imprint.hpp:66
CTempString implements a light-weight string on top of a storage buffer whose lifetime management is ...
Definition: tempstr.hpp:65
Definition: Title.hpp:51
const string & GetTitle(C_E::E_Choice type=C_E::e_not_set) const
If the internal list contains a title (of the specified type, if given), returns the corresponding st...
Definition: Title.cpp:56
@ eLabel_V1
Traditional GetLabel semantics, modeled on the C Toolkit's PubLabelUnique.
@ eLabel_V2
New implementation, in line with GenBank/GenPept REFERENCE JOURNAL fields and the like.
@ eLabel_MaxVersion
Maximum supported version.
@ eLabel_DefaultVersion
Current default version.
int TLabelFlags
binary OR of ELabelFlags
static string GetParenthesizedYear(const CDate &date)
virtual bool GetLabelV2(string *label, TLabelFlags flags) const =0
virtual bool GetLabelV1(string *label, TLabelFlags flags) const =0
static string FixPages(const string &orig_pages)
Canonicalize a range of page numbers, expanding Medline-style 125-35 -> 125-135, F124-34 -> F124-F134...
static bool HasText(const string &s)
static void NoteSup(string *label, const CImprint &imp)
static bool x_GetLabelV1(string *label, bool unique, const CAuth_list *authors, const CImprint *imprint, const CTitle *title, const CCit_book *book, const CCit_jour *journal, const string *title1=0, const string *title2=0, const string *titleunique=0, const string *date=0, const string *volume=0, const string *issue=0, const string *pages=0, bool unpublished=false)
bool GetLabel(string *label, TLabelFlags flags=0, ELabelVersion version=eLabel_DefaultVersion) const override
Append a label to the specified string per the specified flags.
static void MaybeAddSpace(string *label)
static uch flags
static const char ip[]
Definition: des.c:75
#define NULL
Definition: ncbistd.hpp:225
#define ERR_POST(message)
Error posting with file, line number information but without error codes.
Definition: ncbidiag.hpp:186
void Warning(CExceptionArgs_Base &args)
Definition: ncbiexpt.hpp:1191
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
NCBI_NS_STD::string::size_type SIZE_TYPE
Definition: ncbistr.hpp:132
static CTempString TruncateSpaces_Unsafe(const CTempString str, ETrunc where=eTrunc_Both)
Truncate spaces in a string.
Definition: ncbistr.cpp:3191
#define kEmptyStr
Definition: ncbistr.hpp:123
static bool EndsWith(const CTempString str, const CTempString end, ECase use_case=eCase)
Check if a string ends with a specified suffix value.
Definition: ncbistr.hpp:5430
#define NPOS
Definition: ncbistr.hpp:133
CTempString & assign(const char *src_str, size_type len)
Assign new values to the content of the a string.
Definition: tempstr.hpp:733
CTempString substr(size_type pos) const
Obtain a substring from this string, beginning at a given offset.
Definition: tempstr.hpp:776
size_type find_first_not_of(const CTempString match, size_type pos=0) const
Find the first occurrence of any character not in the matching string within the current string,...
Definition: tempstr.hpp:553
size_type find_first_of(const CTempString match, size_type pos=0) const
Find the first occurrence of any character in the matching string within the current string,...
Definition: tempstr.hpp:538
size_type size(void) const
Return the length of the represented array.
Definition: tempstr.hpp:327
static const size_type npos
Definition: tempstr.hpp:72
static const char label[]
bool IsSetVolume(void) const
Check if a value has been assigned to Volume data member.
Definition: Imprint_.hpp:746
const TPart_supi & GetPart_supi(void) const
Get the Part_supi member data.
Definition: Imprint_.hpp:1139
const TVolume & GetVolume(void) const
Get the Volume member data.
Definition: Imprint_.hpp:758
const TPages & GetPages(void) const
Get the Pages member data.
Definition: Imprint_.hpp:852
const TIssue & GetIssue(void) const
Get the Issue member data.
Definition: Imprint_.hpp:805
const TPart_sup & GetPart_sup(void) const
Get the Part_sup member data.
Definition: Imprint_.hpp:988
bool IsSetIssue(void) const
Check if a value has been assigned to Issue data member.
Definition: Imprint_.hpp:793
bool IsSetPart_sup(void) const
part/sup of volume Check if a value has been assigned to Part_sup data member.
Definition: Imprint_.hpp:976
const TDate & GetDate(void) const
Get the Date member data.
Definition: Imprint_.hpp:728
bool IsSetPart_supi(void) const
part/sup on issue Check if a value has been assigned to Part_supi data member.
Definition: Imprint_.hpp:1127
bool IsSetPages(void) const
Check if a value has been assigned to Pages data member.
Definition: Imprint_.hpp:840
bool IsStd(void) const
Check if variant Std is selected.
Definition: Date_.hpp:320
const TStr & GetStr(void) const
Get the variant data.
Definition: Date_.hpp:306
bool IsStr(void) const
Check if variant Str is selected.
Definition: Date_.hpp:300
static int version
Definition: mdb_load.c:29
static unsigned cnt[256]
#define _TROUBLE
#define _ASSERT
else result
Definition: token2.c:20
Modified on Tue Apr 23 07:39:37 2024 by modify_doxy.py rev. 669887