vcl: allow for overriding the default PDF rendering resolution
[LibreOffice.git] / sdext / source / pdfimport / pdfparse / pdfparse.cxx
blob0be394d58eb1adcaeb03c3e33af566d9ebb8db01
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <pdfparse.hxx>
23 // boost using obsolete stuff
24 #if defined(_MSC_VER)
25 #pragma warning(push)
26 #pragma warning(disable:4996)
27 #pragma warning(disable:4503)
28 #endif
30 // workaround windows compiler: do not include multi_pass.hpp
31 #include <boost/spirit/include/classic_core.hpp>
32 #include <boost/spirit/include/classic_utility.hpp>
33 #include <boost/spirit/include/classic_error_handling.hpp>
34 #include <boost/spirit/include/classic_file_iterator.hpp>
35 #include <boost/bind.hpp>
37 #include <string.h>
39 #include <rtl/strbuf.hxx>
40 #include <rtl/ustrbuf.hxx>
41 #include <sal/log.hxx>
43 // disable warnings again because someone along the line has enabled them
44 // (we have included boost headers, what did you expect?)
45 #if defined(_MSC_VER)
46 #pragma warning(push)
47 #pragma warning(disable:4996)
48 #pragma warning(disable:4503)
49 #endif
52 using namespace boost::spirit;
53 using namespace pdfparse;
56 class StringEmitContext : public EmitContext
58 OStringBuffer m_aBuf;
59 public:
60 StringEmitContext() : EmitContext(), m_aBuf(256) {}
62 virtual bool write( const void* pBuf, unsigned int nLen ) throw() override
64 m_aBuf.append( static_cast<const sal_Char*>(pBuf), nLen );
65 return true;
67 virtual unsigned int getCurPos() throw() override { return m_aBuf.getLength(); }
68 virtual bool copyOrigBytes( unsigned int nOrigOffset, unsigned int nLen ) throw() override
69 { return (nOrigOffset+nLen < static_cast<unsigned int>(m_aBuf.getLength()) ) &&
70 write( m_aBuf.getStr() + nOrigOffset, nLen ); }
71 virtual unsigned int readOrigBytes( unsigned int nOrigOffset, unsigned int nLen, void* pBuf ) throw() override
73 if( nOrigOffset+nLen < static_cast<unsigned int>(m_aBuf.getLength()) )
75 memcpy( pBuf, m_aBuf.getStr()+nOrigOffset, nLen );
76 return nLen;
78 return 0;
81 OString getString() { return m_aBuf.makeStringAndClear(); }
84 template< class iteratorT >
85 class PDFGrammar : public grammar< PDFGrammar<iteratorT> >
87 public:
89 explicit PDFGrammar( const iteratorT& first )
90 : m_fDouble( 0.0 ), m_aGlobalBegin( first ) {}
91 ~PDFGrammar()
93 if( !m_aObjectStack.empty() )
94 delete m_aObjectStack.front();
97 double m_fDouble;
98 std::vector< unsigned int > m_aUIntStack;
99 std::vector< PDFEntry* > m_aObjectStack;
100 OString m_aErrorString;
101 iteratorT m_aGlobalBegin;
103 public:
104 struct pdf_string_parser
106 typedef nil_t result_t;
107 template <typename ScannerT>
108 std::ptrdiff_t
109 operator()(ScannerT const& scan, result_t&) const
111 std::ptrdiff_t len = 0;
113 int nBraceLevel = 0;
114 while( ! scan.at_end() )
116 char c = *scan;
117 if( c == ')' )
119 nBraceLevel--;
120 if( nBraceLevel < 0 )
121 break;
123 else if( c == '(' )
124 nBraceLevel++;
125 else if( c == '\\' ) // ignore escaped braces
127 ++len;
128 ++scan.first; // tdf#63054: avoid skipping spaces
129 if( scan.first == scan.last ) // tdf#63054: avoid skipping spaces
130 break;
132 ++len;
133 ++scan;
135 return scan.at_end() ? -1 : len;
139 template< typename ScannerT >
140 struct definition
142 explicit definition( const PDFGrammar<iteratorT>& rSelf )
144 PDFGrammar<iteratorT>* pSelf = const_cast< PDFGrammar<iteratorT>* >( &rSelf );
146 // workaround workshop compiler: comment_p doesn't work
147 // comment = comment_p("%")[boost::bind(&PDFGrammar::pushComment, pSelf, _1, _2 )];
148 comment = lexeme_d[ (ch_p('%') >> *(~ch_p('\r') & ~ch_p('\n')) >> eol_p)[boost::bind(&PDFGrammar::pushComment, pSelf, _1, _2 )] ];
150 boolean = (str_p("true") | str_p("false"))[boost::bind(&PDFGrammar::pushBool, pSelf, _1, _2)];
152 // workaround workshop compiler: confix_p doesn't work
153 //stream = confix_p( "stream", *anychar_p, "endstream" )[boost::bind(&PDFGrammar::emitStream, pSelf, _1, _2 )];
154 stream = (str_p("stream") >> *(anychar_p - str_p("endstream")) >> str_p("endstream"))[boost::bind(&PDFGrammar::emitStream, pSelf, _1, _2 )];
156 name = lexeme_d[
157 ch_p('/')
158 >> (*(anychar_p-chset_p("\t\n\f\r ()<>[]{}/%")-ch_p('\0')))
159 [boost::bind(&PDFGrammar::pushName, pSelf, _1, _2)] ];
161 // workaround workshop compiler: confix_p doesn't work
162 //stringtype = ( confix_p("(",*anychar_p, ")") |
163 // confix_p("<",*xdigit_p, ">") )
164 // [boost::bind(&PDFGrammar::pushString,pSelf, _1, _2)];
166 stringtype = ( ( ch_p('(') >> functor_parser<pdf_string_parser>() >> ch_p(')') ) |
167 ( ch_p('<') >> *xdigit_p >> ch_p('>') ) )
168 [boost::bind(&PDFGrammar::pushString,pSelf, _1, _2)];
170 null_object = str_p( "null" )[boost::bind(&PDFGrammar::pushNull, pSelf, _1, _2)];
172 #ifdef USE_ASSIGN_ACTOR
173 objectref = ( uint_p[push_back_a(pSelf->m_aUIntStack)]
174 >> uint_p[push_back_a(pSelf->m_aUIntStack)]
175 >> ch_p('R')
176 >> eps_p
177 )[boost::bind(&PDFGrammar::pushObjectRef, pSelf, _1, _2)];
178 #else
179 objectref = ( uint_p[boost::bind(&PDFGrammar::push_back_action_uint, pSelf, _1)]
180 >> uint_p[boost::bind(&PDFGrammar::push_back_action_uint, pSelf, _1)]
181 >> ch_p('R')
182 >> eps_p
183 )[boost::bind(&PDFGrammar::pushObjectRef, pSelf, _1, _2)];
184 #endif
186 #ifdef USE_ASSIGN_ACTOR
187 simple_type = objectref | name |
188 ( real_p[assign_a(pSelf->m_fDouble)] >> eps_p )
189 [boost::bind(&PDFGrammar::pushDouble, pSelf, _1, _2)]
190 | stringtype | boolean | null_object;
191 #else
192 simple_type = objectref | name |
193 ( real_p[boost::bind(&PDFGrammar::assign_action_double, pSelf, _1)] >> eps_p )
194 [boost::bind(&PDFGrammar::pushDouble, pSelf, _1, _2)]
195 | stringtype | boolean | null_object;
196 #endif
198 dict_begin = str_p( "<<" )[boost::bind(&PDFGrammar::beginDict, pSelf, _1, _2)];
199 dict_end = str_p( ">>" )[boost::bind(&PDFGrammar::endDict, pSelf, _1, _2)];
201 array_begin = str_p("[")[boost::bind(&PDFGrammar::beginArray,pSelf, _1, _2)];
202 array_end = str_p("]")[boost::bind(&PDFGrammar::endArray,pSelf, _1, _2)];
204 #ifdef USE_ASSIGN_ACTOR
205 object_begin= uint_p[push_back_a(pSelf->m_aUIntStack)]
206 >> uint_p[push_back_a(pSelf->m_aUIntStack)]
207 >> str_p("obj" )[boost::bind(&PDFGrammar::beginObject, pSelf, _1, _2)];
208 #else
209 object_begin= uint_p[boost::bind(&PDFGrammar::push_back_action_uint, pSelf, _1)]
210 >> uint_p[boost::bind(&PDFGrammar::push_back_action_uint, pSelf, _1)]
211 >> str_p("obj" )[boost::bind(&PDFGrammar::beginObject, pSelf, _1, _2)];
212 #endif
213 object_end = str_p( "endobj" )[boost::bind(&PDFGrammar::endObject, pSelf, _1, _2)];
215 xref = str_p( "xref" ) >> uint_p >> uint_p
216 >> lexeme_d[
217 +( repeat_p(10)[digit_p]
218 >> blank_p
219 >> repeat_p(5)[digit_p]
220 >> blank_p
221 >> ( ch_p('n') | ch_p('f') )
222 >> repeat_p(2)[space_p]
223 ) ];
225 dict_element= dict_begin | comment | simple_type
226 | array_begin | array_end | dict_end;
228 object = object_begin
229 >> *dict_element
230 >> !stream
231 >> object_end;
233 trailer = str_p( "trailer" )[boost::bind(&PDFGrammar::beginTrailer,pSelf,_1,_2)]
234 >> *dict_element
235 >> str_p("startxref")
236 >> uint_p
237 >> str_p("%%EOF")[boost::bind(&PDFGrammar::endTrailer,pSelf,_1,_2)];
239 #ifdef USE_ASSIGN_ACTOR
240 pdfrule = ! (lexeme_d[
241 str_p( "%PDF-" )
242 >> uint_p[push_back_a(pSelf->m_aUIntStack)]
243 >> ch_p('.')
244 >> uint_p[push_back_a(pSelf->m_aUIntStack)]
245 >> *((~ch_p('\r') & ~ch_p('\n')))
246 >> eol_p
247 ])[boost::bind(&PDFGrammar::haveFile,pSelf, _1, _2)]
248 >> *( comment | object | ( xref >> trailer ) );
249 #else
250 pdfrule = ! (lexeme_d[
251 str_p( "%PDF-" )
252 >> uint_p[boost::bind(&PDFGrammar::push_back_action_uint, pSelf, _1)]
253 >> ch_p('.')
254 >> uint_p[boost::bind(&PDFGrammar::push_back_action_uint, pSelf, _1)]
255 >> *(~ch_p('\r') & ~ch_p('\n'))
256 >> eol_p
257 ])[boost::bind(&PDFGrammar::haveFile,pSelf, _1, _2)]
258 >> *( comment | object | ( xref >> trailer ) );
259 #endif
261 rule< ScannerT > comment, stream, boolean, name, stringtype, null_object, simple_type,
262 objectref, array, value, dict_element, dict_begin, dict_end,
263 array_begin, array_end, object, object_begin, object_end,
264 xref, trailer, pdfrule;
266 const rule< ScannerT >& start() const { return pdfrule; }
269 #ifndef USE_ASSIGN_ACTOR
270 void push_back_action_uint( unsigned int i )
272 m_aUIntStack.push_back( i );
274 void assign_action_double( double d )
276 m_fDouble = d;
278 #endif
280 static void parseError( const char* pMessage, iteratorT pLocation )
282 throw_( pLocation, pMessage );
285 OString iteratorToString( iteratorT first, iteratorT last ) const
287 OStringBuffer aStr( 32 );
288 while( first != last )
290 aStr.append( *first );
291 ++first;
293 return aStr.makeStringAndClear();
296 void haveFile( iteratorT pBegin, SAL_UNUSED_PARAMETER iteratorT /*pEnd*/ )
298 if( m_aObjectStack.empty() )
300 PDFFile* pFile = new PDFFile();
301 pFile->m_nMinor = m_aUIntStack.back();
302 m_aUIntStack.pop_back();
303 pFile->m_nMajor = m_aUIntStack.back();
304 m_aUIntStack.pop_back();
305 m_aObjectStack.push_back( pFile );
307 else
308 parseError( "found file header in unusual place", pBegin );
311 void pushComment( iteratorT first, iteratorT last )
313 // add a comment to the current stack element
314 PDFComment* pComment =
315 new PDFComment(iteratorToString(first,last));
316 if( m_aObjectStack.empty() )
317 m_aObjectStack.push_back( new PDFPart() );
318 PDFContainer* pContainer = dynamic_cast<PDFContainer*>(m_aObjectStack.back());
319 if( pContainer == nullptr )
320 parseError( "comment without container", first );
321 pContainer->m_aSubElements.emplace_back( pComment );
324 void insertNewValue( std::unique_ptr<PDFEntry> pNewValue, iteratorT pPos )
326 PDFContainer* pContainer = nullptr;
327 const char* pMsg = nullptr;
328 if( ! m_aObjectStack.empty() &&
329 (pContainer = dynamic_cast<PDFContainer*>(m_aObjectStack.back())) != nullptr )
331 if( dynamic_cast<PDFDict*>(pContainer) == nullptr &&
332 dynamic_cast<PDFArray*>(pContainer) == nullptr )
334 PDFObject* pObj = dynamic_cast<PDFObject*>(pContainer);
335 if( pObj )
337 if( pObj->m_pObject == nullptr )
338 pObj->m_pObject = pNewValue.get();
339 else
341 pMsg = "second value for object";
342 pContainer = nullptr;
345 else if( dynamic_cast<PDFDict*>(pNewValue.get()) )
347 PDFTrailer* pTrailer = dynamic_cast<PDFTrailer*>(pContainer);
348 if( pTrailer )
350 if( pTrailer->m_pDict == nullptr )
351 pTrailer->m_pDict = dynamic_cast<PDFDict*>(pNewValue.get());
352 else
353 pContainer = nullptr;
355 else
356 pContainer = nullptr;
358 else
359 pContainer = nullptr;
362 if( pContainer )
363 pContainer->m_aSubElements.emplace_back( std::move(pNewValue) );
364 else
366 if( ! pMsg )
368 if( dynamic_cast<PDFContainer*>(pNewValue.get()) )
369 pMsg = "array without container";
370 else
371 pMsg = "value without container";
373 parseError( pMsg, pPos );
377 void pushName( iteratorT first, iteratorT last )
379 insertNewValue( std::make_unique<PDFName>(iteratorToString(first,last)), first );
382 void pushDouble( iteratorT first, SAL_UNUSED_PARAMETER iteratorT /*last*/ )
384 insertNewValue( std::make_unique<PDFNumber>(m_fDouble), first );
387 void pushString( iteratorT first, iteratorT last )
389 insertNewValue( std::make_unique<PDFString>(iteratorToString(first,last)), first );
392 void pushBool( iteratorT first, iteratorT last )
394 insertNewValue( std::make_unique<PDFBool>( last-first == 4 ), first );
397 void pushNull( iteratorT first, SAL_UNUSED_PARAMETER iteratorT )
399 insertNewValue( std::make_unique<PDFNull>(), first );
403 void beginObject( iteratorT first, SAL_UNUSED_PARAMETER iteratorT /*last*/ )
405 if( m_aObjectStack.empty() )
406 m_aObjectStack.push_back( new PDFPart() );
408 unsigned int nGeneration = m_aUIntStack.back();
409 m_aUIntStack.pop_back();
410 unsigned int nObject = m_aUIntStack.back();
411 m_aUIntStack.pop_back();
413 PDFObject* pObj = new PDFObject( nObject, nGeneration );
414 pObj->m_nOffset = first - m_aGlobalBegin;
416 PDFContainer* pContainer = dynamic_cast<PDFContainer*>(m_aObjectStack.back());
417 if( pContainer &&
418 ( dynamic_cast<PDFFile*>(pContainer) ||
419 dynamic_cast<PDFPart*>(pContainer) ) )
421 pContainer->m_aSubElements.emplace_back( pObj );
422 m_aObjectStack.push_back( pObj );
424 else
425 parseError( "object in wrong place", first );
428 void endObject( iteratorT first, SAL_UNUSED_PARAMETER iteratorT )
430 if( m_aObjectStack.empty() )
431 parseError( "endobj without obj", first );
432 else if( dynamic_cast<PDFObject*>(m_aObjectStack.back()) == nullptr )
433 parseError( "spurious endobj", first );
434 else
435 m_aObjectStack.pop_back();
438 void pushObjectRef( iteratorT first, SAL_UNUSED_PARAMETER iteratorT )
440 unsigned int nGeneration = m_aUIntStack.back();
441 m_aUIntStack.pop_back();
442 unsigned int nObject = m_aUIntStack.back();
443 m_aUIntStack.pop_back();
444 insertNewValue( std::make_unique<PDFObjectRef>(nObject,nGeneration), first );
447 void beginDict( iteratorT first, SAL_UNUSED_PARAMETER iteratorT )
449 PDFDict* pDict = new PDFDict();
450 pDict->m_nOffset = first - m_aGlobalBegin;
452 insertNewValue( std::unique_ptr<PDFEntry>(pDict), first );
453 // will not come here if insertion fails (exception)
454 m_aObjectStack.push_back( pDict );
456 void endDict( iteratorT first, SAL_UNUSED_PARAMETER iteratorT )
458 PDFDict* pDict = nullptr;
459 if( m_aObjectStack.empty() )
460 parseError( "dictionary end without begin", first );
461 else if( (pDict = dynamic_cast<PDFDict*>(m_aObjectStack.back())) == nullptr )
462 parseError( "spurious dictionary end", first );
463 else
464 m_aObjectStack.pop_back();
466 PDFEntry* pOffender = pDict->buildMap();
467 if( pOffender )
469 StringEmitContext aCtx;
470 aCtx.write( "offending dictionary element: ", 30 );
471 pOffender->emit( aCtx );
472 m_aErrorString = aCtx.getString();
473 parseError( m_aErrorString.getStr(), first );
477 void beginArray( iteratorT first, SAL_UNUSED_PARAMETER iteratorT )
479 PDFArray* pArray = new PDFArray();
480 pArray->m_nOffset = first - m_aGlobalBegin;
482 insertNewValue( std::unique_ptr<PDFEntry>(pArray), first );
483 // will not come here if insertion fails (exception)
484 m_aObjectStack.push_back( pArray );
487 void endArray( iteratorT first, SAL_UNUSED_PARAMETER iteratorT )
489 if( m_aObjectStack.empty() )
490 parseError( "array end without begin", first );
491 else if( dynamic_cast<PDFArray*>(m_aObjectStack.back()) == nullptr )
492 parseError( "spurious array end", first );
493 else
494 m_aObjectStack.pop_back();
497 void emitStream( iteratorT first, iteratorT last )
499 if( m_aObjectStack.empty() )
500 parseError( "stream without object", first );
501 PDFObject* pObj = dynamic_cast<PDFObject*>(m_aObjectStack.back());
502 if( pObj && pObj->m_pObject )
504 if( pObj->m_pStream )
505 parseError( "multiple streams in object", first );
507 PDFDict* pDict = dynamic_cast<PDFDict*>(pObj->m_pObject);
508 if( pDict )
510 PDFStream* pStream = new PDFStream( first - m_aGlobalBegin, last - m_aGlobalBegin, pDict );
512 pObj->m_pStream = pStream;
513 pObj->m_aSubElements.emplace_back( pStream );
516 else
517 parseError( "stream without object", first );
520 void beginTrailer( iteratorT first, SAL_UNUSED_PARAMETER iteratorT )
522 if( m_aObjectStack.empty() )
523 m_aObjectStack.push_back( new PDFPart() );
525 PDFTrailer* pTrailer = new PDFTrailer();
526 pTrailer->m_nOffset = first - m_aGlobalBegin;
528 PDFContainer* pContainer = dynamic_cast<PDFContainer*>(m_aObjectStack.back());
529 if( pContainer &&
530 ( dynamic_cast<PDFFile*>(pContainer) ||
531 dynamic_cast<PDFPart*>(pContainer) ) )
533 pContainer->m_aSubElements.emplace_back( pTrailer );
534 m_aObjectStack.push_back( pTrailer );
536 else
537 parseError( "trailer in wrong place", first );
540 void endTrailer( iteratorT first, SAL_UNUSED_PARAMETER iteratorT )
542 if( m_aObjectStack.empty() )
543 parseError( "%%EOF without trailer", first );
544 else if( dynamic_cast<PDFTrailer*>(m_aObjectStack.back()) == nullptr )
545 parseError( "spurious %%EOF", first );
546 else
547 m_aObjectStack.pop_back();
551 #ifdef _WIN32
552 std::unique_ptr<PDFEntry> PDFReader::read( const char* pBuffer, unsigned int nLen )
554 PDFGrammar<const char*> aGrammar( pBuffer );
558 #if OSL_DEBUG_LEVEL > 0
559 boost::spirit::parse_info<const char*> aInfo =
560 #endif
561 boost::spirit::parse( pBuffer,
562 pBuffer+nLen,
563 aGrammar,
564 boost::spirit::space_p );
565 #if OSL_DEBUG_LEVEL > 0
566 SAL_INFO("sdext.pdfimport.pdfparse", "parseinfo: stop = " << aInfo.stop << " (buff=" << pBuffer << ", offset = " << aInfo.stop - pBuffer << "), hit = " << (aInfo.hit ? OUString("true") : OUString("false")) << ", full = " << (aInfo.full ? OUString("true") : OUString("false")) << ", length = " << static_cast<int>(aInfo.length) );
567 #endif
569 catch( const parser_error<const char*, const char*>& rError )
571 #if OSL_DEBUG_LEVEL > 0
572 OString aTmp;
573 unsigned int nElem = aGrammar.m_aObjectStack.size();
574 for( unsigned int i = 0; i < nElem; i++ )
575 aTmp += OStringLiteral(" ") + typeid( *(aGrammar.m_aObjectStack[i]) ).name();
577 SAL_WARN("sdext.pdfimport.pdfparse", "parse error: " << rError.descriptor << " at buffer pos " << rError.where - pBuffer << ", object stack: " << aTmp);
578 #else
579 (void)rError;
580 #endif
583 std::unique_ptr<PDFEntry> pRet;
584 unsigned int nEntries = aGrammar.m_aObjectStack.size();
585 if( nEntries == 1 )
587 pRet.reset(aGrammar.m_aObjectStack.back());
588 aGrammar.m_aObjectStack.pop_back();
590 #if OSL_DEBUG_LEVEL > 0
591 else if( nEntries > 1 )
592 SAL_WARN("sdext.pdfimport.pdfparse", "error got " << nEntries << " stack objects in parse" );
593 #endif
595 return pRet;
597 #endif
599 std::unique_ptr<PDFEntry> PDFReader::read( const char* pFileName )
601 #ifdef _WIN32
602 /* #i106583#
603 since converting to boost 1.39 file_iterator does not work anymore on all Windows systems
604 C++ stdlib istream_iterator does not allow "-" apparently
605 using spirit 2.0 doesn't work in our environment with the MSC
607 So for the time being bite the bullet and read the whole file.
608 FIXME: give Spirit 2.x another try when we upgrade boost again.
610 std::unique_ptr<PDFEntry> pRet;
611 FILE* fp = fopen( pFileName, "rb" );
612 if( fp )
614 fseek( fp, 0, SEEK_END );
615 unsigned int nLen = static_cast<unsigned int>(ftell( fp ));
616 fseek( fp, 0, SEEK_SET );
617 char* pBuf = static_cast<char*>(std::malloc( nLen ));
618 if( pBuf )
620 fread( pBuf, 1, nLen, fp );
621 pRet = read( pBuf, nLen );
622 std::free( pBuf );
624 fclose( fp );
626 return pRet;
627 #else
628 file_iterator<> file_start( pFileName );
629 if( ! file_start )
630 return nullptr;
631 file_iterator<> file_end = file_start.make_end();
632 PDFGrammar< file_iterator<> > aGrammar( file_start );
636 #if OSL_DEBUG_LEVEL > 0
637 boost::spirit::parse_info< file_iterator<> > aInfo =
638 #endif
639 boost::spirit::parse( file_start,
640 file_end,
641 aGrammar,
642 boost::spirit::space_p );
643 #if OSL_DEBUG_LEVEL > 0
644 SAL_INFO("sdext.pdfimport.pdfparse", "parseinfo: stop at offset = " << aInfo.stop - file_start << ", hit = " << (aInfo.hit ? "true" : "false") << ", full = " << (aInfo.full ? "true" : "false") << ", length = " << aInfo.length);
645 #endif
647 catch( const parser_error< const char*, file_iterator<> >& rError )
649 SAL_WARN("sdext.pdfimport.pdfparse", "parse error: " << rError.descriptor << " at buffer pos " << rError.where - file_start);
650 #if OSL_DEBUG_LEVEL > 0
651 OUStringBuffer aTmp;
652 unsigned int nElem = aGrammar.m_aObjectStack.size();
653 for( unsigned int i = 0; i < nElem; i++ )
655 aTmp.append(" ");
656 aTmp.appendAscii(typeid( *(aGrammar.m_aObjectStack[i]) ).name());
658 SAL_WARN("sdext.pdfimport.pdfparse", "parse error object stack: " << aTmp.makeStringAndClear());
659 #endif
662 std::unique_ptr<PDFEntry> pRet;
663 unsigned int nEntries = aGrammar.m_aObjectStack.size();
664 if( nEntries == 1 )
666 pRet.reset(aGrammar.m_aObjectStack.back());
667 aGrammar.m_aObjectStack.pop_back();
669 #if OSL_DEBUG_LEVEL > 0
670 else if( nEntries > 1 )
672 SAL_WARN("sdext.pdfimport.pdfparse", "error got " << nEntries << " stack objects in parse");
673 for( unsigned int i = 0; i < nEntries; i++ )
675 SAL_WARN("sdext.pdfimport.pdfparse", typeid(*aGrammar.m_aObjectStack[i]).name());
676 PDFObject* pObj = dynamic_cast<PDFObject*>(aGrammar.m_aObjectStack[i]);
677 if( pObj )
678 SAL_WARN("sdext.pdfimport.pdfparse", " -> object " << pObj->m_nNumber << " generation " << pObj->m_nGeneration);
679 else
680 SAL_WARN("sdext.pdfimport.pdfparse", "(type " << typeid(*aGrammar.m_aObjectStack[i]).name() << ")");
683 #endif
684 return pRet;
685 #endif // WIN32
688 #if defined(_MSC_VER)
689 #pragma warning(pop)
690 #endif
692 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */