summaryrefslogtreecommitdiff
path: root/lib/Support/LocaleXlocale.inc
blob: 389fe3d1d4fd0aa4b428a8c88978a95fb09842b9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/ManagedStatic.h"
#include <cassert>
#include <xlocale.h>


namespace {
  struct locale_holder {
    locale_holder()
    : l(newlocale(LC_CTYPE_MASK,"en_US.UTF-8",LC_GLOBAL_LOCALE))
    {
      assert(NULL!=l);
    }
    ~locale_holder() {
      freelocale(l);
    }

    int mbswidth(llvm::SmallString<16> s) const {
       // this implementation assumes no '\0' in s
      assert(s.size()==strlen(s.c_str()));

      size_t size = mbstowcs_l(NULL,s.c_str(),0,l);
      assert(size!=(size_t)-1);
      if (size==0)
        return 0;
      llvm::SmallVector<wchar_t,200> ws(size);
      size = mbstowcs_l(&ws[0],s.c_str(),ws.size(),l);
      assert(ws.size()==size);
      return wcswidth_l(&ws[0],ws.size(),l);
    }

    int isprint(int c) const {
      return iswprint_l(c,l);
    }

  private:

    locale_t l;
  };

  llvm::ManagedStatic<locale_holder> l;
}

namespace llvm {
namespace sys {
namespace locale {

int columnWidth(StringRef s) {
  int width = l->mbswidth(s);
  assert(width>=0);
  return width;
}

bool isPrint(int c) {
  return l->isprint(c);
}

}
}
}