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

Go to the SVN repository for this file.

1 /* $Id: asn_element_primitive.cpp 47464 2023-04-20 00:19:10Z evgeniev $
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  * Authors: Roman Katargin
27  *
28  * File Description:
29  *
30  */
31 
32 #include <ncbi_pch.hpp>
33 #include <corelib/ncbifloat.h>
34 
37 
40 
41 #include "asn_styles.hpp"
42 
43 #include <serial/objectinfo.hpp>
44 
45 #include <wx/dcclient.h>
46 #include <wx/txtstrm.h>
47 
49 
50 const int kTextBlockLines = 50;
51 const unsigned int kMaxTextLine = 78;
52 
54  TTypeInfo type, TConstObjectPtr ptr) const
55 {
56  _ASSERT(type->GetTypeFamily() == eTypeFamilyPrimitive);
57 
58  const CPrimitiveTypeInfo* primitiveType =
60 
61  EPrimitiveValueType primitiveValueType = primitiveType->GetPrimitiveValueType();
62  switch(primitiveValueType) {
64  {{
65  ostream << CAsnStyles::GetStyle(CAsnStyles::kNullValue) << "NULL";
66  }}
67  break;
68  case ePrimitiveValueBool :
69  {{
70  bool value = primitiveType->GetValueBool(ptr);
72  ostream << (value ? "TRUE" : "FALSE");
73  }}
74  break;
75  case ePrimitiveValueEnum : // enum
76  {{
77  const CEnumeratedTypeInfo* enumType =
79 
80  string valueName;
81  // the call to GetValueString throws exception if value ia an arbitrary interger GB-2987
82  try {
83  enumType->GetValueString(ptr, valueName);
84  } catch (const CException&) {
85  }
86 
87  if (!valueName.empty()) {
88  ostream << DefaultStyle() << valueName;
89  } else {
90  Int4 value = enumType->GetValueInt4(ptr);
91  ostream << DefaultStyle() << NStr::NumericToString(value);
92 
93  try {
94  const CEnumeratedTypeValues& values = enumType->Values();
95  if (values.IsBitset()) {
96  string bitSet = values.GetDisplayName(value);
97  if (!bitSet.empty()) {
98  ostream << CAsnStyles::GetStyle(CAsnStyles::kComment) << " --("
99  << DefaultStyle() << bitSet << CAsnStyles::GetStyle(CAsnStyles::kComment) << ")--";
100  }
101  }
102  } catch (const CException&) {
103  }
104  }
105  }}
106  break;
107  case ePrimitiveValueInteger : // (signed|unsigned) (char|short|int|long)
108  {{
109  string value;
110  if (primitiveType->IsSigned())
111  NStr::Int8ToString(value, primitiveType->GetValueInt8(ptr));
112  else
113  NStr::UInt8ToString(value, primitiveType->GetValueInt8(ptr));
115  }}
116  break;
117  case ePrimitiveValueReal :
118  {{
119  size_t digits = DBL_DIG;
120  double data = primitiveType->GetValueDouble(ptr);
122 
123  if (isnan(data)) {
124  ostream << CAsnStyles::GetStyle(CAsnStyles::kError) << "NaN";
125  break;
126  }
127  if (!finite(data)) {
128  ostream << CAsnStyles::GetStyle(CAsnStyles::kError) << "Inf";
129  break;
130  }
131  if ( data == 0.0 ) {
132  ostream << "{ 0, 10, 0 }";
133  break;
134  }
135 
136  char buffer[128];
137  // ensure buffer is large enough to fit result
138  // (additional bytes are for sign, dot and exponent)
139  _ASSERT(sizeof(buffer) > digits + 16);
140  int width = sprintf(buffer, "%.*e", int(digits-1), data);
141  if ( width <= 0 || width >= int(sizeof(buffer) - 1) ) {
142  ostream << CAsnStyles::GetStyle(CAsnStyles::kError) << "buffer overflow";
143  break;
144  }
145  _ASSERT(int(strlen(buffer)) == width);
146  char* dotPos = strchr(buffer, '.');
147  _ASSERT(dotPos);
148  char* ePos = strchr(dotPos, 'e');
149  _ASSERT(ePos);
150 
151  // now we have:
152  // mantissa with dot - buffer:ePos
153  // exponent - (ePos+1):
154 
155  int exp;
156  // calculate exponent
157  if ( sscanf(ePos + 1, "%d", &exp) != 1 ) {
158  ostream << CAsnStyles::GetStyle(CAsnStyles::kError) << "double value conversion error";
159  break;
160  }
161 
162  // remove trailing zeroes
163  int fractDigits = int(ePos - dotPos - 1);
164  while ( fractDigits > 0 && ePos[-1] == '0' ) {
165  --ePos;
166  --fractDigits;
167  }
168 
169  // now we have:
170  // mantissa with dot without trailing zeroes - buffer:ePos
171 
172  string tmp1, tmp2;
173  tmp1 = string(buffer, dotPos - buffer) + string(dotPos + 1, fractDigits);
174  NStr::Int8ToString(tmp2, exp - fractDigits);
175  ostream << "{ " << tmp1 << ", 10, " << tmp2 << " }";
176  }}
177  break;
178  case ePrimitiveValueString : // string|char*|const char*
179  {{
181  string value;
182  primitiveType->GetValueString(ptr, value);
183  ostream << "\"";
184  size_t length = value.length();
185  while (length > 0) {
186  size_t curLength = ostream.CurrentRowLength();
187  size_t posBreak = 0, pos = 0;
188  long count = min(length, 78 - curLength);
189 
190  for (pos = 0; count > 0; pos++, count--) {
191  unsigned char c = value[pos];
192  if (c == '"') count--;
193  if (isspace(c) || c == '\'')
194  posBreak = pos;
195  }
196 
197  if (pos < length) {
198  unsigned char c = value[pos];
199  if (isspace(c) || c == '\'')
200  posBreak = pos;
201  }
202 
203  // can we wrap string at word break?
204  if (posBreak == 0 || pos == length)
205  posBreak = pos;
206 
207  string tmp;
208  for (pos = 0; pos < posBreak; pos++) {
209  unsigned char c = value[pos];
210  tmp += c;
211  if (c == '"') tmp += c;
212  }
213  ostream << tmp;
214  value = value.substr(posBreak);
215  length = length - posBreak;
216  if (length > 0)
217  ostream << NewLine();
218  }
219  ostream << "\"";
220  }}
221  break;
223  _ASSERT(false); // Should be handled by CAsnOctetStringBlock
224  break;
225  default:
226  break;
227  }
228 
229  x_RenderComma(ostream);
230 }
231 
233 {
234 public:
236 
237  virtual StreamHint GetHint() const { return kTextPos; }
238  virtual CStyledTextOStream& operator<< (const string& text)
239  {
240  m_TextPosX += text.length();
241  return *this;
242  }
243  virtual int CurrentRowLength() const { return m_TextPosX; }
244 
245  virtual void SetStyle(const CTextStyle* style);
246  virtual void SetDefaultStyle() {}
247  virtual void Indent (size_t steps) { m_TextPosX += steps; }
248  virtual void NewLine() { m_TextPosX = 0; }
249 
250  size_t GetDataOffset() const { return m_DataOffset; }
251 
252 private:
255 };
256 
258 {
261 }
262 
264  const CMemberId& memberId,
265  TTypeInfo type,
266  TConstObjectPtr ptr,
267  size_t indent,
268  CAsnBioContext* bioContext)
269 {
270  CTextItem* retval = 0;
271 
272  TTypeInfo realType = type;
273  TConstObjectPtr realPtr = ptr;
274 
275  GetRealObject(realType, realPtr);
277  const CPrimitiveTypeInfo* primitiveType =
279 
280  EPrimitiveValueType primitiveValueType = primitiveType->GetPrimitiveValueType();
281  if (primitiveValueType == ePrimitiveValueOctetString) {
282  size_t data_size;
283 
284  {{
285  vector<char> value;
286  primitiveType->GetValueOctetString(realPtr, value);
287  data_size = value.size();
288  }}
289 
290  CAsnOctetStringBlock* element = new CAsnOctetStringBlock(true, 0, memberId, type, ptr, indent, bioContext);
291  retval = element;
292 
294  element->RenderText(os, NULL);
295  size_t dataOffset = os.GetDataOffset();
296  size_t first_line = 0;
297  if (dataOffset + 3 <= kMaxTextLine)
298  first_line = (kMaxTextLine - dataOffset - 1)/2;
299 
300  size_t total_lines = 1 + (((data_size - first_line)*2 + 2) + kMaxTextLine - 1)/kMaxTextLine;
301  size_t blocks_num = (total_lines + kTextBlockLines - 1)/kTextBlockLines;
302  if (blocks_num > 1) {
303  CCompositeTextItem* group = new CCompositeTextItem();
304  retval = group;
305 
306  element->SetTrailComma(false);
307  group->AddItem(element);
308 
309  size_t full_line = kMaxTextLine/2;
310 
311  size_t offset = first_line + (kTextBlockLines - 1)*full_line;
312  while (--blocks_num > 0) {
313  element = new CAsnOctetStringBlock(false, offset, memberId, type, ptr, indent, bioContext);
314  element->SetTrailComma(blocks_num == 1);
315  group->AddItem(element);
316  offset += full_line*kTextBlockLines;
317  }
318  }
319  }
320  else
321  retval = new CAsnElementPrimitive(memberId, type, ptr, indent, bioContext);
322 
323  return retval;
324 }
325 
327 {
328  if (m_FirstBlock) {
330  }
331  else {
333  TConstObjectPtr ptr = m_Ptr;
334 
335  GetRealObject(type, ptr);
336  RenderValue(ostream, context, type, ptr);
337  ostream << NewLine();
338  }
339 }
340 
342 {
343  ostream << "\'" << DefaultStyle() << "H";
344 }
345 
347  TTypeInfo type, TConstObjectPtr ptr) const
348 {
349  _ASSERT(type->GetTypeFamily() == eTypeFamilyPrimitive);
350 
351  const CPrimitiveTypeInfo* primitiveType =
354 
355  vector<char> value;
356  primitiveType->GetValueOctetString(ptr, value);
357 
359 
360  int lines = 1;
361 
362  if (m_FirstBlock) {
364 
365  size_t curLength = ostream.CurrentRowLength();
366  if (curLength + 2 > kMaxTextLine) {
367  ostream << NewLine();
368  ++lines;
369  }
370  }
371 
372  size_t i = m_DataOffset;
373  for (;;) {
374  if (i < value.size()) {
375  size_t curLength = ostream.CurrentRowLength();
376  size_t count = min(value.size()-i, (kMaxTextLine - curLength)/2);
377  string tmp;
378  static const char HEX[] = "0123456789ABCDEF";
379 
380  while (count-- > 0) {
381  char c = value[i];
382  tmp += HEX[(c >> 4) & 0xf];
383  tmp += HEX[c & 0xf];
384  ++i;
385  }
386  ostream << tmp;
387  }
388 
389  if (i >= value.size()) {
390  size_t curLength = ostream.CurrentRowLength();
391  if (curLength + 2 <= kMaxTextLine) {
392  s_FinishOctetString(ostream);
393  x_RenderComma(ostream);
394  break;
395  }
396  else {
397  if (lines < kTextBlockLines) {
398  ostream << NewLine();
399  ++lines;
400  s_FinishOctetString(ostream);
401  x_RenderComma(ostream);
402  }
403  break;
404  }
405  }
406 
407  if (lines == kTextBlockLines)
408  break;
409 
410  ostream << NewLine();
411  ++lines;
412  }
413 }
414 
const unsigned int kMaxTextLine
static void s_FinishOctetString(CStyledTextOStream &ostream)
const int kTextBlockLines
void x_RenderComma(CStyledTextOStream &ostream) const
TConstObjectPtr m_Ptr
void SetTrailComma(bool fTrailComma)
static void GetRealObject(TTypeInfo &type, TConstObjectPtr &ptr)
virtual void x_RenderText(CStyledTextOStream &ostream, CTextPanelContext *context) const
CAsnElementPrimitive(const CMemberId &memberId, TTypeInfo type, TConstObjectPtr ptr, size_t indent, CAsnBioContext *bioContext)
static CTextItem * CreateItem(const CMemberId &memberId, TTypeInfo type, TConstObjectPtr ptr, size_t indent, CAsnBioContext *bioContext)
virtual void RenderValue(CStyledTextOStream &ostream, CTextPanelContext *context, TTypeInfo type, TConstObjectPtr ptr) const
virtual void RenderValue(CStyledTextOStream &ostream, CTextPanelContext *context, TTypeInfo type, TConstObjectPtr ptr) const
virtual void x_RenderText(CStyledTextOStream &ostream, CTextPanelContext *context) const
static const CTextStyle & GetStyle(Element element)
Definition: asn_styles.cpp:40
virtual void Indent(size_t steps)
virtual CStyledTextOStream & operator<<(const string &text)
virtual StreamHint GetHint() const
virtual int CurrentRowLength() const
virtual void SetStyle(const CTextStyle *style)
void AddItem(ITextItem *item, bool updatePositions=true)
virtual int CurrentRowLength() const =0
void RenderText(CStyledTextOStream &ostream, CTextPanelContext *context) const
Definition: text_item.hpp:164
CTypeInfo class contains all information about C++ types (both basic and classes): members and layout...
Definition: typeinfo.hpp:76
static int type
Definition: getdata.c:31
static char tmp[3200]
Definition: utf8.c:42
int offset
Definition: replacements.h:160
char data[12]
Definition: iconv.c:80
string
Definition: cgiapp.hpp:690
#define NULL
Definition: ncbistd.hpp:225
#define isnan
Definition: ncbifloat.h:92
#define finite
Define value of finite (Is Finite).
Definition: ncbifloat.h:103
bool IsBitset(void) const
Definition: enumvalues.hpp:147
string GetDisplayName(TEnumValueType value) const
Definition: enumerated.cpp:172
const void * TConstObjectPtr
Definition: serialdef.hpp:59
EPrimitiveValueType
Primitive value type.
Definition: serialdef.hpp:147
static const TObjectType * SafeCast(TTypeInfo type)
Definition: serialutil.hpp:76
@ ePrimitiveValueSpecial
null, void
Definition: serialdef.hpp:148
@ ePrimitiveValueOctetString
vector<(signed|unsigned)? char>
Definition: serialdef.hpp:155
@ ePrimitiveValueString
string|char*|const char*
Definition: serialdef.hpp:153
@ ePrimitiveValueInteger
(signed|unsigned) (char|short|int|long)
Definition: serialdef.hpp:151
@ ePrimitiveValueBool
bool
Definition: serialdef.hpp:149
@ ePrimitiveValueEnum
enum
Definition: serialdef.hpp:154
@ ePrimitiveValueReal
float|double
Definition: serialdef.hpp:152
@ eTypeFamilyPrimitive
Definition: serialdef.hpp:139
int32_t Int4
4-byte (32-bit) signed integer
Definition: ncbitype.h:102
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
static string Int8ToString(Int8 value, TNumToStringFlags flags=0, int base=10)
Convert Int8 to string.
Definition: ncbistr.hpp:5153
static enable_if< is_arithmetic< TNumeric >::value||is_convertible< TNumeric, Int8 >::value, string >::type NumericToString(TNumeric value, TNumToStringFlags flags=0, int base=10)
Convert numeric value to string.
Definition: ncbistr.hpp:673
static string UInt8ToString(Uint8 value, TNumToStringFlags flags=0, int base=10)
Convert UInt8 to string.
Definition: ncbistr.hpp:5162
EPrimitiveValueType GetPrimitiveValueType(void) const
virtual void GetValueString(TConstObjectPtr objectPtr, string &value) const
Definition: stdtypes.cpp:501
virtual void GetValueString(TConstObjectPtr objectPtr, string &value) const override
Definition: enumerated.cpp:397
ETypeFamily GetTypeFamily(void) const
virtual void GetValueOctetString(TConstObjectPtr objectPtr, vector< char > &value) const
Definition: stdtypes.cpp:513
virtual Int4 GetValueInt4(TConstObjectPtr objectPtr) const override
Definition: enumerated.cpp:324
virtual bool IsSigned(void) const
virtual double GetValueDouble(TConstObjectPtr objectPtr) const
Definition: stdtypes.cpp:469
virtual bool GetValueBool(TConstObjectPtr objectPtr) const
Definition: stdtypes.cpp:377
const CEnumeratedTypeValues & Values(void) const
Definition: enumerated.hpp:57
virtual Int8 GetValueInt8(TConstObjectPtr objectPtr) const
Definition: stdtypes.cpp:445
unsigned int
A callback function used to compare two keys in a database.
Definition: types.hpp:1210
int i
static void text(MDB_val *v)
Definition: mdb_dump.c:62
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1227
int isspace(Uchar c)
Definition: ncbictype.hpp:69
Floating-point support routines.
T min(T x_, T y_)
static const char HEX[]
Definition: objostrasn.cpp:873
#define count
static uint8_t * buffer
Definition: pcre2test.c:1016
string indent(" ")
#define tmp1
Definition: type.c:6
#define _ASSERT
static CS_CONTEXT * context
Definition: will_convert.c:21
Modified on Fri Sep 20 14:57:01 2024 by modify_doxy.py rev. 669887