1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #include "NSPRLogModulesParser.h"
8 
9 #include "mozilla/Tokenizer.h"
10 
11 const char kDelimiters[] = ", ";
12 const char kAdditionalWordChars[] = "_-.*";
13 
14 namespace mozilla {
15 
NSPRLogModulesParser(const char * aLogModules,const std::function<void (const char *,LogLevel,int32_t)> & aCallback)16 void NSPRLogModulesParser(
17     const char* aLogModules,
18     const std::function<void(const char*, LogLevel, int32_t)>& aCallback) {
19   if (!aLogModules) {
20     return;
21   }
22 
23   Tokenizer parser(aLogModules, kDelimiters, kAdditionalWordChars);
24   nsAutoCString moduleName;
25 
26   Tokenizer::Token rustModSep =
27       parser.AddCustomToken("::", Tokenizer::CASE_SENSITIVE);
28 
29   auto readModuleName = [&](nsAutoCString& moduleName) -> bool {
30     moduleName.Truncate();
31     nsDependentCSubstring sub;
32     parser.Record();
33     // If the name doesn't include at least one word, we've reached the end.
34     if (!parser.ReadWord(sub)) {
35       return false;
36     }
37     // We will exit this loop if when any of the condition fails
38     while (parser.Check(rustModSep) && parser.ReadWord(sub)) {
39     }
40     // Claim will include characters of the last sucessfully read item
41     parser.Claim(moduleName, Tokenizer::INCLUDE_LAST);
42     return true;
43   };
44 
45   // Format: LOG_MODULES="Foo:2,Bar, Baz:5,rust_crate::mod::file:5"
46   while (readModuleName(moduleName)) {
47     // Next should be :<level>, default to Error if not provided.
48     LogLevel logLevel = LogLevel::Error;
49     int32_t levelValue = 0;
50     if (parser.CheckChar(':')) {
51       // NB: If a level isn't provided after the ':' we assume the default
52       //     Error level is desired. This differs from NSPR which will stop
53       //     processing the log module string in this case.
54       if (parser.ReadSignedInteger(&levelValue)) {
55         logLevel = ToLogLevel(levelValue);
56       }
57     }
58 
59     aCallback(moduleName.get(), logLevel, levelValue);
60 
61     // Skip ahead to the next token.
62     parser.SkipWhites();
63   }
64 }
65 
66 }  // namespace mozilla
67