pdfviewer: do not submit, uploaded for backup, and will be done actually after I refactor the params for functions, to put the char* params in a structure: report errors and warnings in pdf, infrastructure

Review URL: https://codereview.chromium.org/23902018

git-svn-id: http://skia.googlecode.com/svn/trunk@11262 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/experimental/PdfViewer/pdfparser/native/SkPdfNativeDoc.cpp b/experimental/PdfViewer/pdfparser/native/SkPdfNativeDoc.cpp
index f278ea1..ef5276b 100644
--- a/experimental/PdfViewer/pdfparser/native/SkPdfNativeDoc.cpp
+++ b/experimental/PdfViewer/pdfparser/native/SkPdfNativeDoc.cpp
@@ -8,6 +8,7 @@
 #include "SkPdfNativeDoc.h"
 #include "SkPdfNativeTokenizer.h"
 #include "SkPdfNativeObject.h"
+#include "SkPdfReporter.h"
 
 #include <stdio.h>
 #include <string.h>
@@ -107,7 +108,7 @@
         fclose(file);
         if (!ok) {
             sk_free(content);
-            // TODO(edisonn): report read error
+            SkPdfReport(kFatalError_SkPdfIssueSeverity, kReadStreamError_SkPdfIssue, "could not read file", NULL, NULL);
             // TODO(edisonn): not nice to return like this from constructor, create a static
             // function that can report NULL for failures.
             return;  // Doc will have 0 pages
@@ -125,7 +126,7 @@
     const unsigned char* xrefstartKeywordLine = previousLineHome(fFileContent, xrefByteOffsetLine);
 
     if (strcmp((char*)xrefstartKeywordLine, "startxref") != 0) {
-        // TODO(edisonn): report/issue
+        SkPdfReport(kWarning_SkPdfIssueSeverity, kMissingToken_SkPdfIssue, "Could not find startxref", NULL, NULL);
     }
 
     long xrefByteOffset = atol((const char*)xrefByteOffsetLine);
@@ -189,6 +190,7 @@
             current = nextObject(0, current, end, &token, NULL, NULL PUT_TRACK_STREAM_ARGS_EXPL2(0, fFileContent));
             // TODO(edisonn): must be obj, return error if not? ignore ?
             if (!token.isKeyword("obj")) {
+                SkPdfReport(kWarning_SkPdfIssueSeverity, kMissingToken_SkPdfIssue, "Could not find obj", NULL, NULL);
                 continue;
             }
 
@@ -203,6 +205,8 @@
 
             fObjects[id].fResolvedReference = obj;
             fObjects[id].fObj = obj;
+            fObjects[id].fIsReferenceResolved = true;
+
 
             // set objects
         } else if (token.isKeyword("trailer")) {
@@ -227,7 +231,6 @@
         }
     }
 
-
     if (fRootCatalogRef) {
         fRootCatalog = (SkPdfCatalogDictionary*)resolveReference(fRootCatalogRef);
         if (fRootCatalog->isDictionary() && fRootCatalog->valid()) {
@@ -252,6 +255,7 @@
     const unsigned char* current = nextObject(0, xrefStart, trailerEnd, &xref, NULL, NULL PUT_TRACK_STREAM_ARGS_EXPL2(0, fFileContent));
 
     if (!xref.isKeyword("xref")) {
+        SkPdfReport(kWarning_SkPdfIssueSeverity, kMissingToken_SkPdfIssue, "Could not find sref", NULL, NULL);
         return trailerEnd;
     }
 
@@ -261,6 +265,7 @@
         const unsigned char* previous = current;
         current = nextObject(0, current, trailerEnd, &token, NULL, NULL PUT_TRACK_STREAM_ARGS_EXPL2(0, fFileContent));
         if (!token.isInteger()) {
+            SkPdfReport(kInfo_SkPdfIssueSeverity, kNoIssue_SkPdfIssue, "Done readCrossReferenceSection", NULL, NULL);
             return previous;
         }
 
@@ -269,7 +274,7 @@
         current = nextObject(0, current, trailerEnd, &token, NULL, NULL PUT_TRACK_STREAM_ARGS_EXPL2(0, fFileContent));
 
         if (!token.isInteger()) {
-            // TODO(edisonn): report/warning
+            SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, "readCrossReferenceSection", &token, SkPdfNativeObject::kInteger_PdfObjectType, NULL);
             return current;
         }
 
@@ -279,7 +284,7 @@
             token.reset();
             current = nextObject(0, current, trailerEnd, &token, NULL, NULL PUT_TRACK_STREAM_ARGS_EXPL2(0, fFileContent));
             if (!token.isInteger()) {
-                // TODO(edisonn): report/warning
+                SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, "readCrossReferenceSection", &token, SkPdfNativeObject::kInteger_PdfObjectType, NULL);
                 return current;
             }
             int offset = (int)token.intValue();
@@ -287,7 +292,7 @@
             token.reset();
             current = nextObject(0, current, trailerEnd, &token, NULL, NULL PUT_TRACK_STREAM_ARGS_EXPL2(0, fFileContent));
             if (!token.isInteger()) {
-                // TODO(edisonn): report/warning
+                SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, "readCrossReferenceSection", &token, SkPdfNativeObject::kInteger_PdfObjectType, NULL);
                 return current;
             }
             int generation = (int)token.intValue();
@@ -295,14 +300,14 @@
             token.reset();
             current = nextObject(0, current, trailerEnd, &token, NULL, NULL PUT_TRACK_STREAM_ARGS_EXPL2(0, fFileContent));
             if (!token.isKeyword() || token.lenstr() != 1 || (*token.c_str() != 'f' && *token.c_str() != 'n')) {
-                // TODO(edisonn): report/warning
+                SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, "readCrossReferenceSection: f or n expected", &token, SkPdfNativeObject::kKeyword_PdfObjectType, NULL);
                 return current;
             }
 
             addCrossSectionInfo(startId + i, generation, offset, *token.c_str() == 'f');
         }
     }
-    // TODO(edisonn): it should never get here? there is no trailer?
+    SkPdfReport(kInfo_SkPdfIssueSeverity, kNoIssue_SkPdfIssue, "Unexpected end of readCrossReferenceSection", NULL, NULL);
     return current;
 }
 
@@ -319,6 +324,7 @@
         if (!trailerKeyword.isKeyword() || strlen("trailer") != trailerKeyword.lenstr() ||
             strncmp(trailerKeyword.c_str(), "trailer", strlen("trailer")) != 0) {
             // TODO(edisonn): report warning, rebuild trailer from objects.
+            SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, "readTrailer: trailer keyword expected", &trailerKeyword, SkPdfNativeObject::kKeyword_PdfObjectType, NULL);
             return current;
         }
     }
@@ -336,7 +342,7 @@
     if (storeCatalog) {
         SkPdfNativeObject* ref = trailer->Root(NULL);
         if (ref == NULL || !ref->isReference()) {
-            // TODO(edisonn): oops, we have to fix the corrup pdf file
+            SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, "readTrailer: unexpected root reference", ref, SkPdfNativeObject::kReference_PdfObjectType, NULL);
             return current;
         }
         fRootCatalogRef = ref;
@@ -381,28 +387,33 @@
 
     current = nextObject(0, current, end, &idObj, NULL, NULL PUT_TRACK_STREAM_ARGS_EXPL2(0, fFileContent));
     if (current >= end) {
-        // TODO(edisonn): report warning/error
+        SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kReadStreamError_SkPdfIssue, "reading id", NULL, NULL);
         return NULL;
     }
 
     current = nextObject(0, current, end, &generationObj, NULL, NULL PUT_TRACK_STREAM_ARGS_EXPL2(0, fFileContent));
     if (current >= end) {
-        // TODO(edisonn): report warning/error
+        SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kReadStreamError_SkPdfIssue, "reading generation", NULL, NULL);
         return NULL;
     }
 
     current = nextObject(0, current, end, &objKeyword, NULL, NULL PUT_TRACK_STREAM_ARGS_EXPL2(0, fFileContent));
     if (current >= end) {
-        // TODO(edisonn): report warning/error
+        SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kReadStreamError_SkPdfIssue, "reading keyword obj", NULL, NULL);
         return NULL;
     }
 
-    if (!idObj.isInteger() || !generationObj.isInteger() || id != idObj.intValue()/* || generation != generationObj.intValue()*/) {
-        // TODO(edisonn): report warning/error
+    if (!idObj.isInteger() || id != idObj.intValue()) {
+        SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, "readObject: unexpected id", &idObj, SkPdfNativeObject::kInteger_PdfObjectType, NULL);
+    }
+
+    // TODO(edisonn): verify that the generation is the right one
+    if (!generationObj.isInteger() /* || generation != generationObj.intValue()*/) {
+        SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, "readObject: unexpected generation", &generationObj, SkPdfNativeObject::kInteger_PdfObjectType, NULL);
     }
 
     if (!objKeyword.isKeyword() || strcmp(objKeyword.c_str(), "obj") != 0) {
-        // TODO(edisonn): report warning/error
+        SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, "readObject: unexpected obj keyword", &objKeyword, SkPdfNativeObject::kKeyword_PdfObjectType, NULL);
     }
 
     current = nextObject(1, current, end, dict, fAllocator, this PUT_TRACK_STREAM_ARGS_EXPL2(0, fFileContent));
@@ -543,7 +554,7 @@
 
         // TODO(edisonn): verify id and gen expected
         if (id < 0 || id >= fObjects.count()) {
-            // TODO(edisonn): report error/warning
+            SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kReadStreamError_SkPdfIssue, "resolve reference id out of bounds", NULL, NULL);
             return NULL;
         }
 
@@ -553,7 +564,7 @@
             printf("\nresolve(%s) = %s\n", ref->toString(0).c_str(), fObjects[id].fResolvedReference->toString(0, ref->toString().size() + 13).c_str());
 #endif
 
-            // TODO(edisonn): for known good documents, assert here THAT THE REFERENCE IS NOT null
+            SkPdfReportIf(!fObjects[id].fResolvedReference, kIgnoreError_SkPdfIssueSeverity, kBadReference_SkPdfIssue, "ref is NULL", NULL, NULL);
             return fObjects[id].fResolvedReference;
         }
 
diff --git a/experimental/PdfViewer/pdfparser/native/SkPdfNativeObject.cpp b/experimental/PdfViewer/pdfparser/native/SkPdfNativeObject.cpp
index 54daf17..73f765d 100644
--- a/experimental/PdfViewer/pdfparser/native/SkPdfNativeObject.cpp
+++ b/experimental/PdfViewer/pdfparser/native/SkPdfNativeObject.cpp
@@ -18,11 +18,13 @@
 #include "SkBitmap.h"
 #include "SkPdfFont.h"
 
+#include "SkPdfReporter.h"
+
 SkPdfNativeObject SkPdfNativeObject::kNull = SkPdfNativeObject::makeNull(PUT_TRACK_PARAMETERS_SRC0);
 
 bool SkPdfNativeObject::applyFlateDecodeFilter() {
     if (!SkFlate::HaveFlate()) {
-        // TODO(edisonn): warn, make callers handle it
+        SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kNoFlateLibrary_SkPdfIssue, "forgot to link with flate library?", NULL, NULL);
         return false;
     }
 
@@ -43,7 +45,7 @@
 
         return true;
     } else {
-        // TODO(edisonn): warn, make callers handle it
+        SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kBadStream_SkPdfIssue, "inflate failed", this, NULL);
         return false;
     }
 }
@@ -61,7 +63,7 @@
     } else if (strcmp(name, "DCTDecode") == 0) {
         return applyDCTDecodeFilter();
     }
-    // TODO(edisonn): allert, not supported, but should be implemented asap
+    SkPdfReport(kCodeWarning_SkPdfIssueSeverity, kNYI_SkPdfIssue, "filter not supported", this, NULL);
     return false;
 }
 
@@ -69,6 +71,7 @@
     SkPdfMarkObjectUsed();
 
     if (!hasStream()) {
+        SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kBadStream_SkPdfIssue, "No Stream", this, NULL);
         return false;
     }
 
@@ -93,7 +96,7 @@
                     break;
                 }
             } else {
-                // TODO(edisonn): report warning
+                SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kIncositentSyntax_SkPdfIssue, "filter name should be a Name", this, NULL);
             }
         }
     }
@@ -102,7 +105,9 @@
 }
 
 void SkPdfNativeObject::releaseData() {
-    // TODO(edisonn): report here unused objects
+#ifdef PDF_TRACK_OBJECT_USAGE
+    SkPdfReportIf(!fUsed, kInfo_SkPdfIssueSeverity, NULL, this, "Unused object in rendering");
+#endif  // PDF_TRACK_OBJECT_USAGE
 
     SkPdfMarkObjectUnused();
 
diff --git a/experimental/PdfViewer/pdfparser/native/SkPdfNativeObject.h b/experimental/PdfViewer/pdfparser/native/SkPdfNativeObject.h
index 344d6c6..94c0547 100644
--- a/experimental/PdfViewer/pdfparser/native/SkPdfNativeObject.h
+++ b/experimental/PdfViewer/pdfparser/native/SkPdfNativeObject.h
@@ -38,25 +38,31 @@
 class SkPdfNativeObject {
  public:
      enum ObjectType {
-         kInvalid_PdfObjectType,
+         // The type will have only one of these values, but for error reporting, we make it an enum
+         // so it can easily report that something was expected to be one of a few types
+         kInvalid_PdfObjectType = 1 << 1,
 
-         kBoolean_PdfObjectType,
-         kInteger_PdfObjectType,
-         kReal_PdfObjectType,
-         kString_PdfObjectType,
-         kHexString_PdfObjectType,
-         kName_PdfObjectType,
-         kKeyword_PdfObjectType,
-         //kStream_PdfObjectType,  //  attached to a Dictionary
-         kArray_PdfObjectType,
-         kDictionary_PdfObjectType,
-         kNull_PdfObjectType,
+         kBoolean_PdfObjectType = 1 << 2,
+         kInteger_PdfObjectType = 1 << 3,
+         kReal_PdfObjectType = 1 << 4,
+         _kNumber_PdfObjectType = kInteger_PdfObjectType | kReal_PdfObjectType,
+         kString_PdfObjectType = 1 << 5,
+         kHexString_PdfObjectType = 1 << 6,
+         _kAnyString_PdfObjectType = kString_PdfObjectType | kHexString_PdfObjectType,
+         kName_PdfObjectType = 1 << 7,
+         kKeyword_PdfObjectType = 1 << 8,
+         _kStream_PdfObjectType = 1 << 9,  //  attached to a Dictionary, do not use
+         kArray_PdfObjectType = 1 << 10,
+         kDictionary_PdfObjectType = 1 << 11,
+         kNull_PdfObjectType = 1 << 12,
 
          // TODO(edisonn): after the pdf has been loaded completely, resolve all references
          // try the same thing with delayed loaded ...
-         kReference_PdfObjectType,
+         kReference_PdfObjectType = 1 << 13,
 
-         kUndefined_PdfObjectType,  // per 1.4 spec, if the same key appear twice in the dictionary, the value is undefined
+         kUndefined_PdfObjectType = 1 << 14,  // per 1.4 spec, if the same key appear twice in the dictionary, the value is undefined
+
+         _kObject_PdfObjectType = -1,
      };
 
      enum DataType {
diff --git a/experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.cpp b/experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.cpp
index 4e0e4c4..6438855 100644
--- a/experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.cpp
+++ b/experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.cpp
@@ -811,11 +811,15 @@
     // skip white spaces
     start = skipPdfWhiteSpaces(level, start, end);
 
+    if (start >= end) {
+        return end;
+    }
+
     current = endOfPdfToken(level, start, end);
 
     // no token, len would be 0
-    if (current == start) {
-        return NULL;
+    if (current == start || current == end) {
+        return end;
     }
 
     int tokenLen = current - start;